From 50a8778acf2c7e82b1adc702c3f75135dbf9aa85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?L=C3=A9lio=20Brun?= <lelio.brun@isae-supaero.fr>
Date: Fri, 25 Jun 2021 12:35:52 +0200
Subject: [PATCH] refactoring first step

---
 src/annotations.ml                            |   2 +-
 src/annotations.mli                           |   5 +
 src/arrow.ml                                  |   2 +-
 src/automata.ml                               |  21 +-
 src/automata.mli                              |  14 +
 src/backends/Ada/ada_backend.mli              |   0
 src/backends/Ada/ada_backend_adb.mli          |   0
 src/backends/Ada/ada_backend_ads.mli          |   0
 src/backends/Ada/ada_backend_wrapper.mli      |   0
 src/backends/Ada/misc_lustre_function.ml      |  28 +-
 src/backends/Ada/misc_lustre_function.mli     |   0
 src/backends/Ada/misc_printer.mli             |   1 +
 src/backends/C/c_backend.mli                  |   0
 src/backends/C/c_backend_cmake.mli            |   0
 src/backends/C/c_backend_common.ml            |   4 +-
 src/backends/C/c_backend_common.mli           |   5 +
 src/backends/C/c_backend_header.mli           |   0
 src/backends/C/c_backend_main.mli             |   0
 src/backends/C/c_backend_makefile.mli         |   0
 src/backends/C/c_backend_mauve.mli            |   0
 src/backends/C/c_backend_spec.ml              |  33 +-
 src/backends/C/c_backend_spec.mli             |   3 +
 src/backends/C/c_backend_src.mli              |   0
 src/backends/EMF/EMF_backend.mli              |   0
 src/backends/EMF/EMF_common.mli               |   0
 src/backends/EMF/EMF_library_calls.mli        |   0
 src/backends/Horn/horn_backend.mli            |   0
 .../Horn/horn_backend_collecting_sem.mli      |   0
 src/backends/Horn/horn_backend_common.mli     |   0
 src/backends/Horn/horn_backend_printers.mli   |   0
 src/backends/Horn/horn_backend_traces.mli     |   0
 src/backends/Java/java_backend.mli            |   0
 src/backends/VHDL/vhdl_ast.mli                |   0
 src/backends/VHDL/vhdl_test.mli               |   0
 src/backends/backends.ml                      |  13 +-
 src/backends/backends.mli                     |   3 +
 src/basic_library.mli                         |  17 +
 src/causality.mli                             |  62 ++++
 src/checks/access.mli                         |   0
 src/checks/algebraicLoop.mli                  |   0
 src/checks/init_calculus.mli                  |   0
 src/checks/liveness.ml                        |   2 +
 src/checks/liveness.mli                       |  18 +
 src/checks/stateless.ml                       |   1 +
 src/checks/stateless.mli                      |  16 +
 src/clock_calculus.ml                         |  10 +-
 src/clock_calculus.mli                        |   9 +
 src/clock_predef.mli                          |   4 +
 src/clocks.ml                                 |  71 ++--
 src/clocks.mli                                |  97 ++++++
 src/compiler_common.ml                        |  22 +-
 src/compiler_common.mli                       |  13 +
 src/compiler_stages.ml                        |   5 +-
 src/compiler_stages.mli                       |   0
 src/corelang.ml                               |  29 +-
 src/corelang.mli                              |  20 +-
 src/delay.ml                                  |  27 +-
 src/delay.mli                                 |  17 +
 src/delay_predef.mli                          |   4 +
 src/dune                                      |   3 +-
 src/error.ml                                  |  13 +-
 src/error.mli                                 |  18 +
 src/expand.mli                                |   0
 src/features/machine_types/machine_types.ml   |   6 +-
 src/global.ml                                 |   8 +-
 src/global.mli                                |   3 +
 src/init_predef.mli                           |   0
 src/inliner.ml                                |  13 +-
 src/inliner.mli                               |   0
 src/log.ml                                    |   4 +-
 src/log.mli                                   |   1 +
 src/lusic.ml                                  |   4 +-
 src/lusic.mli                                 |  14 +
 src/lustre_live.ml                            |   2 +-
 src/lustre_live.mli                           |   6 +
 src/lustre_types.ml                           |  42 +--
 src/lustre_types.mli                          | 229 +++++++++++++
 src/lustre_utils.ml                           |   2 +-
 src/lustre_utils.mli                          |   0
 src/machine_code.ml                           |   8 +-
 src/machine_code_common.ml                    |  40 ++-
 src/machine_code_common.mli                   | 116 ++++---
 ...e_code_types.ml => machine_code_types.mli} |   5 +-
 src/main_lustre_compiler.mli                  |   0
 src/main_lustre_testgen.mli                   |   0
 src/main_lustre_verifier.mli                  |   0
 src/mmap.mli                                  |   0
 src/modules.ml                                |   2 +-
 src/modules.mli                               |   4 +-
 src/mutation.mli                              |   0
 src/normalization.ml                          |  12 +-
 src/normalization.mli                         |   1 +
 src/optimize_machine.ml                       |  26 +-
 src/optimize_machine.mli                      |   0
 src/optimize_prog.mli                         |   0
 src/options.ml                                |  30 +-
 src/options.mli                               |  78 +++++
 src/options_management.ml                     |  24 +-
 src/options_management.mli                    |   6 +
 src/parsers/lexerLustreSpec.mll               |   4 +-
 src/parsers/lexer_lustre.mll                  |   4 +-
 src/parsers/parse.ml                          |   4 +-
 src/parsers/parse.mli                         |  20 ++
 src/pathConditions.mli                        |   0
 src/plugins/mpfr/lustrec_mpfr.mli             |   1 +
 src/plugins/pluginList.ml                     |   2 +-
 src/plugins/pluginList.mli                    |   2 +
 src/plugins/pluginType.ml                     |   6 +
 src/plugins/pluginType.mli                    |  25 ++
 src/plugins/plugins.mli                       |   4 +
 src/plugins/salsa/machine_salsa_opt.mli       |   0
 src/plugins/salsa/salsaDatatypes.mli          |   0
 src/plugins/salsa/salsa_plugin.mli            |   0
 src/plugins/scopes/scopes.ml                  |  21 +-
 src/plugins/scopes/scopes.mli                 |   0
 src/printers.ml                               |  87 ++---
 src/printers.mli                              |  17 +
 src/scheduling.ml                             |   8 +-
 src/scheduling.mli                            |   9 +
 ...scheduling_type.ml => scheduling_type.mli} |   0
 src/sortProg.ml                               |  11 +-
 src/sortProg.mli                              |   4 +
 src/spec.mli                                  |   0
 src/spec_common.mli                           |  19 +
 src/spec_types.ml                             |   3 +-
 src/spec_types.mli                            |  66 ++++
 src/splitting.mli                             |   5 +
 src/tools/importer/main_lustre_importer.mli   |   0
 src/tools/importer/vhdl_deriving_yojson.mli   | 294 ++++++++++++++++
 src/tools/importer/vhdl_json_lib.mli          |   8 +
 src/tools/seal/seal_export.mli                |   0
 src/tools/seal/seal_extract.mli               |   0
 src/tools/seal/seal_slice.mli                 |   0
 src/tools/seal/seal_utils.mli                 |   0
 src/tools/seal/seal_verifier.mli              |   0
 src/tools/stateflow/sf_sem.mli                |   0
 src/tools/tiny/tiny_utils.mli                 |   0
 src/tools/tiny/tiny_verifier.mli              |   0
 src/tools/zustre/zustre_analyze.mli           |   0
 src/tools/zustre/zustre_cex.mli               |   0
 src/tools/zustre/zustre_common.mli            |   0
 src/tools/zustre/zustre_data.mli              |   0
 src/tools/zustre/zustre_test.mli              |   0
 src/tools/zustre/zustre_verifier.mli          |   0
 src/type_predef.ml                            |   8 +-
 src/type_predef.mli                           |  32 ++
 src/types.ml                                  | 324 ++++++++----------
 src/types.mli                                 | 161 +++++++++
 src/typing.ml                                 |  32 +-
 src/typing.mli                                |  28 ++
 src/utils/dimension.ml                        |  42 +--
 src/utils/dimension.mli                       |  46 +++
 src/utils/env.ml                              |   4 +-
 src/utils/env.mli                             |  12 +
 src/utils/location.ml                         |  35 +-
 src/utils/location.mli                        |  10 +
 src/utils/utils.ml                            |  26 +-
 src/utils/utils.mli                           |  93 +++++
 src/verifierList.mli                          |   0
 src/verifierType.mli                          |  17 +
 src/verifiers.mli                             |   0
 src/version.mli                               |   3 +
 162 files changed, 2141 insertions(+), 654 deletions(-)
 create mode 100644 src/annotations.mli
 create mode 100644 src/automata.mli
 create mode 100644 src/backends/Ada/ada_backend.mli
 create mode 100644 src/backends/Ada/ada_backend_adb.mli
 create mode 100644 src/backends/Ada/ada_backend_ads.mli
 create mode 100644 src/backends/Ada/ada_backend_wrapper.mli
 create mode 100644 src/backends/Ada/misc_lustre_function.mli
 create mode 100644 src/backends/Ada/misc_printer.mli
 create mode 100644 src/backends/C/c_backend.mli
 create mode 100644 src/backends/C/c_backend_cmake.mli
 create mode 100644 src/backends/C/c_backend_common.mli
 create mode 100644 src/backends/C/c_backend_header.mli
 create mode 100644 src/backends/C/c_backend_main.mli
 create mode 100644 src/backends/C/c_backend_makefile.mli
 create mode 100644 src/backends/C/c_backend_mauve.mli
 create mode 100644 src/backends/C/c_backend_spec.mli
 create mode 100644 src/backends/C/c_backend_src.mli
 create mode 100644 src/backends/EMF/EMF_backend.mli
 create mode 100644 src/backends/EMF/EMF_common.mli
 create mode 100644 src/backends/EMF/EMF_library_calls.mli
 create mode 100644 src/backends/Horn/horn_backend.mli
 create mode 100644 src/backends/Horn/horn_backend_collecting_sem.mli
 create mode 100644 src/backends/Horn/horn_backend_common.mli
 create mode 100644 src/backends/Horn/horn_backend_printers.mli
 create mode 100644 src/backends/Horn/horn_backend_traces.mli
 create mode 100644 src/backends/Java/java_backend.mli
 create mode 100644 src/backends/VHDL/vhdl_ast.mli
 create mode 100644 src/backends/VHDL/vhdl_test.mli
 create mode 100644 src/backends/backends.mli
 create mode 100644 src/basic_library.mli
 create mode 100644 src/causality.mli
 create mode 100644 src/checks/access.mli
 create mode 100644 src/checks/algebraicLoop.mli
 create mode 100644 src/checks/init_calculus.mli
 create mode 100644 src/checks/liveness.mli
 create mode 100644 src/checks/stateless.mli
 create mode 100644 src/clock_calculus.mli
 create mode 100644 src/clock_predef.mli
 create mode 100644 src/clocks.mli
 create mode 100644 src/compiler_common.mli
 create mode 100644 src/compiler_stages.mli
 create mode 100644 src/delay.mli
 create mode 100644 src/delay_predef.mli
 create mode 100644 src/error.mli
 create mode 100644 src/expand.mli
 create mode 100644 src/global.mli
 create mode 100644 src/init_predef.mli
 create mode 100644 src/inliner.mli
 create mode 100644 src/log.mli
 create mode 100644 src/lusic.mli
 create mode 100644 src/lustre_live.mli
 create mode 100644 src/lustre_types.mli
 create mode 100644 src/lustre_utils.mli
 rename src/{machine_code_types.ml => machine_code_types.mli} (95%)
 create mode 100644 src/main_lustre_compiler.mli
 create mode 100644 src/main_lustre_testgen.mli
 create mode 100644 src/main_lustre_verifier.mli
 create mode 100644 src/mmap.mli
 create mode 100644 src/mutation.mli
 create mode 100644 src/optimize_machine.mli
 create mode 100644 src/optimize_prog.mli
 create mode 100644 src/options.mli
 create mode 100644 src/options_management.mli
 create mode 100644 src/parsers/parse.mli
 create mode 100644 src/pathConditions.mli
 create mode 100644 src/plugins/mpfr/lustrec_mpfr.mli
 create mode 100644 src/plugins/pluginList.mli
 create mode 100644 src/plugins/pluginType.mli
 create mode 100644 src/plugins/plugins.mli
 create mode 100644 src/plugins/salsa/machine_salsa_opt.mli
 create mode 100644 src/plugins/salsa/salsaDatatypes.mli
 create mode 100644 src/plugins/salsa/salsa_plugin.mli
 create mode 100644 src/plugins/scopes/scopes.mli
 create mode 100644 src/printers.mli
 create mode 100644 src/scheduling.mli
 rename src/{scheduling_type.ml => scheduling_type.mli} (100%)
 create mode 100644 src/sortProg.mli
 create mode 100644 src/spec.mli
 create mode 100644 src/spec_common.mli
 create mode 100644 src/spec_types.mli
 create mode 100644 src/splitting.mli
 create mode 100644 src/tools/importer/main_lustre_importer.mli
 create mode 100644 src/tools/importer/vhdl_deriving_yojson.mli
 create mode 100644 src/tools/importer/vhdl_json_lib.mli
 create mode 100644 src/tools/seal/seal_export.mli
 create mode 100644 src/tools/seal/seal_extract.mli
 create mode 100644 src/tools/seal/seal_slice.mli
 create mode 100644 src/tools/seal/seal_utils.mli
 create mode 100644 src/tools/seal/seal_verifier.mli
 create mode 100644 src/tools/stateflow/sf_sem.mli
 create mode 100644 src/tools/tiny/tiny_utils.mli
 create mode 100644 src/tools/tiny/tiny_verifier.mli
 create mode 100644 src/tools/zustre/zustre_analyze.mli
 create mode 100644 src/tools/zustre/zustre_cex.mli
 create mode 100644 src/tools/zustre/zustre_common.mli
 create mode 100644 src/tools/zustre/zustre_data.mli
 create mode 100644 src/tools/zustre/zustre_test.mli
 create mode 100644 src/tools/zustre/zustre_verifier.mli
 create mode 100644 src/type_predef.mli
 create mode 100644 src/types.mli
 create mode 100644 src/typing.mli
 create mode 100644 src/utils/dimension.mli
 create mode 100644 src/utils/env.mli
 create mode 100644 src/utils/location.mli
 create mode 100644 src/utils/utils.mli
 create mode 100644 src/verifierList.mli
 create mode 100644 src/verifierType.mli
 create mode 100644 src/verifiers.mli
 create mode 100644 src/version.mli

diff --git a/src/annotations.ml b/src/annotations.ml
index 7da8dfb6..a82bf185 100644
--- a/src/annotations.ml
+++ b/src/annotations.ml
@@ -9,7 +9,7 @@
 (*                                                                  *)
 (********************************************************************)
 
-open Lustre_types
+open Utils
 
 (* Associate to each annotation key the pair (node, expr tag) *)
 let expr_annotations : (string list, ident * tag) Hashtbl.t = Hashtbl.create 13
diff --git a/src/annotations.mli b/src/annotations.mli
new file mode 100644
index 00000000..9fe9f3fa
--- /dev/null
+++ b/src/annotations.mli
@@ -0,0 +1,5 @@
+open Utils
+
+val add_node_ann: ident -> string list -> unit
+val add_expr_ann: ident -> tag -> string list -> unit
+val get_expr_annotations: ident list -> (ident * tag) list
diff --git a/src/arrow.ml b/src/arrow.ml
index f2e933df..a5b57e96 100644
--- a/src/arrow.ml
+++ b/src/arrow.ml
@@ -32,7 +32,7 @@ let arrow_top_decl () =
     top_decl_desc = Node arrow_desc;
     top_decl_owner = Options_management.core_dependency "arrow";
     top_decl_itf = false;
-    top_decl_loc = Location.dummy_loc;
+    top_decl_loc = Location.dummy;
   }
 
 let td_is_arrow td = Corelang.node_name td = arrow_id
diff --git a/src/automata.ml b/src/automata.ml
index d75a4d58..04c8f6f0 100644
--- a/src/automata.ml
+++ b/src/automata.ml
@@ -53,16 +53,17 @@ let add_branch (loc, expr, restart, st) cont =
          mkexpr loc (Expr_tuple [ mkbool loc restart; mkident loc st ]),
          cont ))
 
-let mkhandler loc st unless until locals (stmts, asserts, annots) =
+let mkhandler hand_loc hand_state hand_unless hand_until hand_locals
+    (hand_stmts, hand_asserts, hand_annots) =
   {
-    hand_state = st;
-    hand_unless = unless;
-    hand_until = until;
-    hand_locals = locals;
-    hand_stmts = stmts;
-    hand_asserts = asserts;
-    hand_annots = annots;
-    hand_loc = loc;
+    hand_state;
+    hand_unless;
+    hand_until;
+    hand_locals;
+    hand_stmts;
+    hand_asserts;
+    hand_annots;
+    hand_loc;
   }
 
 let mkautomata loc id handlers =
@@ -297,7 +298,7 @@ let node_of_assign_until nused used node aut_id aut_state handler =
   in
   let new_var_locals = node_vars_of_idents node writes in
   let var_outputs =
-    List.sort IdentModule.compare (node_vars_of_idents node writes)
+    List.sort VDeclModule.compare (node_vars_of_idents node writes)
   in
   let new_var_outputs =
     List.map
diff --git a/src/automata.mli b/src/automata.mli
new file mode 100644
index 00000000..1e478988
--- /dev/null
+++ b/src/automata.mli
@@ -0,0 +1,14 @@
+open Utils
+open Lustre_types
+
+val mkhandler: Location.t -> ident ->  (Location.t * expr * bool * ident) list
+  -> (Location.t * expr * bool * ident) list
+  -> var_decl list
+    -> statement list * assert_t list * expr_annot list -> handler_desc
+
+val mkautomata: Location.t -> ident -> handler_desc list -> automata_desc
+
+val expand_decls: program_t -> program_t
+
+(* val expand_automata: (ident -> bool) -> (ident -> bool) -> ident -> typedef_desc -> node_desc ->
+ *   automata_desc -> top_decl list * var_decl list * statement list *)
diff --git a/src/backends/Ada/ada_backend.mli b/src/backends/Ada/ada_backend.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Ada/ada_backend_adb.mli b/src/backends/Ada/ada_backend_adb.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Ada/ada_backend_ads.mli b/src/backends/Ada/ada_backend_ads.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Ada/ada_backend_wrapper.mli b/src/backends/Ada/ada_backend_wrapper.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Ada/misc_lustre_function.ml b/src/backends/Ada/misc_lustre_function.ml
index 1647ba77..794ab385 100644
--- a/src/backends/Ada/misc_lustre_function.ml
+++ b/src/backends/Ada/misc_lustre_function.ml
@@ -77,12 +77,14 @@ let rec find_submachine_step_call ident instr_list =
 let pp_eq_type typ1 typ2 =
   let get_basic typ =
     match (Types.repr typ).Types.tdesc with
-    | Types.Tbasic Types.Basic.Tint ->
-      Types.Basic.Tint
-    | Types.Tbasic Types.Basic.Treal ->
-      Types.Basic.Treal
-    | Types.Tbasic Types.Basic.Tbool ->
-      Types.Basic.Tbool
+    | Types.Tbasic t ->
+      t
+    (* | Types.Tbasic Types.Basic.Tint ->
+     *   Types.Basic.Tint
+     * | Types.Tbasic Types.Basic.Treal ->
+     *   Types.Basic.Treal
+     * | Types.Tbasic Types.Basic.Tbool ->
+     *   Types.Basic.Tbool *)
     | _ ->
       assert false
     (*TODO*)
@@ -91,7 +93,7 @@ let pp_eq_type typ1 typ2 =
 
 (** Check that two types are the same. @param t1 a type @param t2 an other type
     @param return true if the two types are Tbasic or Tunivar and equal **)
-let rec check_type_equal (t1 : Types.type_expr) (t2 : Types.type_expr) =
+let rec check_type_equal (t1 : Types.t) (t2 : Types.t) =
   match (Types.repr t1).Types.tdesc, (Types.repr t2).Types.tdesc with
   | Types.Tbasic x, Types.Tbasic y ->
     x = y
@@ -114,8 +116,8 @@ let rec check_type_equal (t1 : Types.type_expr) (t2 : Types.type_expr) =
     be polymorphic. @param subsitution the base substitution @param type_poly
     the type which can be polymorphic @param typ the type to match type_poly
     with **)
-let unification (substituion : (int * Types.type_expr) list)
-    ((type_poly : Types.type_expr), (typ : Types.type_expr)) =
+let unification (substituion : (int * Types.t) list)
+    ((type_poly : Types.t), (typ : Types.t)) =
   assert (not (is_Tunivar typ));
   (* If type_poly is polymorphic *)
   if is_Tunivar type_poly then
@@ -205,12 +207,8 @@ let get_instance identifier typed_submachines =
 (*Usefull for debug*)
 let pp_type_debug fmt typ =
   match (Types.repr typ).Types.tdesc with
-  | Types.Tbasic Types.Basic.Tint ->
-    Format.fprintf fmt "INTEGER"
-  | Types.Tbasic Types.Basic.Treal ->
-    Format.fprintf fmt "FLOAT"
-  | Types.Tbasic Types.Basic.Tbool ->
-    Format.fprintf fmt "BOOLEAN"
+  | Types.Tbasic t ->
+    Types.BasicT.pp fmt t
   | Types.Tunivar ->
     Format.fprintf fmt "POLY(%i)" typ.Types.tid
   | _ ->
diff --git a/src/backends/Ada/misc_lustre_function.mli b/src/backends/Ada/misc_lustre_function.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Ada/misc_printer.mli b/src/backends/Ada/misc_printer.mli
new file mode 100644
index 00000000..df403db0
--- /dev/null
+++ b/src/backends/Ada/misc_printer.mli
@@ -0,0 +1 @@
+type printer = Format.formatter -> unit
diff --git a/src/backends/C/c_backend.mli b/src/backends/C/c_backend.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_cmake.mli b/src/backends/C/c_backend_cmake.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml
index 4abd0122..454f2bff 100644
--- a/src/backends/C/c_backend_common.ml
+++ b/src/backends/C/c_backend_common.ml
@@ -852,12 +852,12 @@ let pp_clear m self pp_var fmt var =
 
 (*** Common functions for main ***)
 
-let pp_print_file file_suffix fmt (typ, arg) =
+let pp_file file_suffix fmt (typ, arg) =
   fprintf fmt
     "@[<v 2>if (traces) {@,fprintf(f_%s, \"%%%s\\n\", %s);@,fflush(f_%s);@]@,}"
     file_suffix typ arg file_suffix
 
-let print_put_var fmt file_suffix name var_type var_id =
+let pp_put_var fmt file_suffix name var_type var_id =
   let pp_file = pp_print_file ("out" ^ file_suffix) in
   let unclocked_t = Types.unclock_type var_type in
   fprintf fmt "@[<v>%a@]"
diff --git a/src/backends/C/c_backend_common.mli b/src/backends/C/c_backend_common.mli
new file mode 100644
index 00000000..98fb6dc2
--- /dev/null
+++ b/src/backends/C/c_backend_common.mli
@@ -0,0 +1,5 @@
+open Utils
+
+val pp_file_decl: Format.formatter -> ident -> int -> unit
+val pp_file_open: Format.formatter -> ident -> int -> string
+val pp_put_var: Format.formatter -> string -> ident -> Types.t -> ident -> unit
diff --git a/src/backends/C/c_backend_header.mli b/src/backends/C/c_backend_header.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_main.mli b/src/backends/C/c_backend_main.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_makefile.mli b/src/backends/C/c_backend_makefile.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_mauve.mli b/src/backends/C/c_backend_mauve.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/C/c_backend_spec.ml b/src/backends/C/c_backend_spec.ml
index 2c355abe..8143ff47 100644
--- a/src/backends/C/c_backend_spec.ml
+++ b/src/backends/C/c_backend_spec.ml
@@ -42,8 +42,6 @@ let pp_acsl_line pp fmt = fprintf fmt "//%@ @[<h>%a@]" pp
 
 let pp_acsl_line' pp fmt = fprintf fmt "/*%@ @[<h>%a@] */" pp
 
-let pp_acsl_line_cut pp fmt = fprintf fmt "%a@," (pp_acsl_line pp)
-
 let pp_requires pp_req fmt = fprintf fmt "requires %a;" pp_req
 
 let pp_ensures pp_ens fmt = fprintf fmt "ensures %a;" pp_ens
@@ -152,8 +150,6 @@ let pp_separated' =
     ~pp_prologue:(fun fmt () -> pp_print_string fmt "\\separated(")
     ~pp_epilogue:pp_print_cpar pp_var_decl
 
-let pp_par pp fmt = fprintf fmt "(%a)" pp
-
 let pp_forall pp_l pp_r fmt (l, r) =
   fprintf fmt "@[<v 2>\\forall %a;@,%a@]" pp_l l pp_r r
 
@@ -162,8 +158,6 @@ let pp_exists pp_l pp_r fmt (l, r) =
 
 let pp_equal pp_l pp_r fmt (l, r) = fprintf fmt "%a == %a" pp_l l pp_r r
 
-let pp_different pp_l pp_r fmt (l, r) = fprintf fmt "%a != %a" pp_l l pp_r r
-
 let pp_implies pp_l pp_r fmt (l, r) =
   fprintf fmt "@[<v>%a ==>@ %a@]" pp_l l pp_r r
 
@@ -174,8 +168,6 @@ let pp_and_l pp_v fmt =
     ~pp_sep:(fun fmt () -> fprintf fmt "@,&& ")
     pp_v fmt
 
-let pp_or pp_l pp_r fmt (l, r) = fprintf fmt "@[<v>%a @ || %a@]" pp_l l pp_r r
-
 let pp_or_l pp_v fmt =
   pp_print_list ~pp_open_box:pp_open_vbox0
     ~pp_sep:(fun fmt () -> fprintf fmt "@,|| ")
@@ -242,8 +234,6 @@ let pp_assign_spec m self_l pp_var_l indirect_l self_r pp_var_r indirect_r fmt
   reset_loop_counter ();
   aux var_type fmt reordered_loop_vars
 
-let pp_nothing fmt () = pp_print_string fmt "\\nothing"
-
 let pp_memory_pack_aux ?i pp_mem pp_self fmt (name, mem, self) =
   fprintf fmt "%s_pack%a(@[<hov>%a,@ %a@])" name
     (pp_print_option pp_print_int)
@@ -253,11 +243,6 @@ let pp_memory_pack pp_mem pp_self fmt (mp, mem, self) =
   pp_memory_pack_aux ?i:mp.mpindex pp_mem pp_self fmt
     (mp.mpname.node_id, mem, self)
 
-let pp_memory_pack_aux' ?i fmt =
-  pp_memory_pack_aux ?i pp_print_string pp_print_string fmt
-
-let pp_memory_pack' fmt = pp_memory_pack pp_print_string pp_print_string fmt
-
 let pp_transition_aux ?i m pp_mem_in pp_mem_out pp_var fmt
     (name, vars, mem_in, mem_out) =
   let stateless = fst (get_stateless_status m) in
@@ -276,15 +261,9 @@ let pp_transition m pp_mem_in pp_mem_out pp_var fmt (t, mem_in, mem_out) =
     (t.tname.node_id, t.tvars, mem_in, mem_out)
 
 let pp_transition_aux' ?i m =
-  pp_transition_aux ?i m pp_print_string pp_print_string pp_var_decl
-
-let pp_transition_aux'' ?i m =
   pp_transition_aux ?i m pp_print_string pp_print_string (fun fmt v ->
       (if is_output m v then pp_ptr_decl else pp_var_decl) fmt v)
 
-let pp_transition' m =
-  pp_transition m pp_print_string pp_print_string pp_var_decl
-
 let pp_reset_cleared pp_mem_in pp_mem_out fmt (name, mem_in, mem_out) =
   fprintf fmt "%s_reset_cleared(@[<hov>%a,@ %a@])" name pp_mem_in mem_in
     pp_mem_out mem_out
@@ -455,7 +434,7 @@ module PrintSpec = struct
       | Or fs ->
         pp_or_l pp_spec' fmt fs
       | Imply (a, b) ->
-        pp_par (pp_implies pp_spec' pp_spec') fmt (a, b)
+        pp_paren (pp_implies pp_spec' pp_spec') fmt (a, b)
       | Exists (xs, a) ->
         pp_exists (pp_locals m) pp_spec' fmt (xs, a)
       | Forall (xs, a) ->
@@ -475,7 +454,7 @@ module PrintSpec = struct
       | StateVarPack (StateVar v) ->
         let v' = vdecl_to_val v in
         let inst = find_arrow m in
-        pp_par
+        pp_paren
           (pp_implies
              (pp_not (pp_initialization pp_access'))
              (pp_assign_spec m mem_out
@@ -650,12 +629,6 @@ let pp_reset_cleared_def fmt m =
       ( (name, (name, mem_in), (name, mem_out)),
         (mem_in, ((mem_out, 0), (name, mem_out)), (mem_out, mem_in)) )
 
-let pp_at pp_p fmt (p, l) = fprintf fmt "\\at(%a, %s)" pp_p p l
-
-let label_pre = "Pre"
-
-let pp_at_pre pp_p fmt p = pp_at pp_p fmt (p, label_pre)
-
 let pp_register_chain ?(indirect = true) ptr =
   pp_print_list
     ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr)
@@ -812,7 +785,7 @@ module SrcMod = struct
             outputs
             (pp_requires pp_separated')
             outputs (pp_assigns pp_ptr_decl) outputs
-            (pp_ensures (pp_transition_aux'' m))
+            (pp_ensures (pp_transition_aux' m))
             (name, inputs @ outputs, "", "")
         else
           fprintf fmt
diff --git a/src/backends/C/c_backend_spec.mli b/src/backends/C/c_backend_spec.mli
new file mode 100644
index 00000000..8a982275
--- /dev/null
+++ b/src/backends/C/c_backend_spec.mli
@@ -0,0 +1,3 @@
+module HdrMod: C_backend_header.MODIFIERS_HDR
+module SrcMod: C_backend_src.MODIFIERS_SRC
+module MakefileMod: C_backend_makefile.MODIFIERS_MKF
diff --git a/src/backends/C/c_backend_src.mli b/src/backends/C/c_backend_src.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/EMF/EMF_backend.mli b/src/backends/EMF/EMF_backend.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/EMF/EMF_common.mli b/src/backends/EMF/EMF_common.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/EMF/EMF_library_calls.mli b/src/backends/EMF/EMF_library_calls.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Horn/horn_backend.mli b/src/backends/Horn/horn_backend.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Horn/horn_backend_collecting_sem.mli b/src/backends/Horn/horn_backend_collecting_sem.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Horn/horn_backend_common.mli b/src/backends/Horn/horn_backend_common.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Horn/horn_backend_printers.mli b/src/backends/Horn/horn_backend_printers.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Horn/horn_backend_traces.mli b/src/backends/Horn/horn_backend_traces.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/Java/java_backend.mli b/src/backends/Java/java_backend.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/VHDL/vhdl_ast.mli b/src/backends/VHDL/vhdl_ast.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/VHDL/vhdl_test.mli b/src/backends/VHDL/vhdl_test.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/backends/backends.ml b/src/backends/backends.ml
index 22da34e0..0f37e533 100644
--- a/src/backends/backends.ml
+++ b/src/backends/backends.ml
@@ -2,7 +2,7 @@
 let join_guards = ref true
 
 let setup () =
-  if !Options.output = "emf" then (
+  if !Options.output = Options.OutEMF then (
     (* Not merging branches *)
     join_guards := false;
     (* In case of a default "int" type, substitute it with the legal int32 value *)
@@ -10,21 +10,22 @@ let setup () =
   if !Options.optimization < 0 then join_guards := false
 
 let is_functional () =
-  match !Options.output with
-  | "horn" | "lustre" | "acsl" | "emf" ->
+  let open Options in
+  match !output with
+  | OutHorn | OutLustre | OutEMF ->
     true
   | _ ->
     false
 
 (* Special treatment of arrows in lustre backend. We want to keep them *)
-let unfold_arrow () = match !Options.output with "lustre" -> false | _ -> true
+let unfold_arrow () = match !Options.output with Options.OutLustre -> false | _ -> true
 
 (* Forcing ite normalization *)
-let alias_ite () = match !Options.output with "emf" -> true | _ -> false
+let alias_ite () = match !Options.output with Options.OutEMF -> true | _ -> false
 
 (* Forcing basic functions normalization *)
 let alias_internal_fun () =
-  match !Options.output with "emf" -> true | _ -> false
+  match !Options.output with Options.OutEMF -> true | _ -> false
 
 let get_normalization_params () =
   {
diff --git a/src/backends/backends.mli b/src/backends/backends.mli
new file mode 100644
index 00000000..80fcce8c
--- /dev/null
+++ b/src/backends/backends.mli
@@ -0,0 +1,3 @@
+val setup: unit -> unit
+val is_functional: unit -> bool
+val join_guards: bool ref
diff --git a/src/basic_library.mli b/src/basic_library.mli
new file mode 100644
index 00000000..2727025c
--- /dev/null
+++ b/src/basic_library.mli
@@ -0,0 +1,17 @@
+open Utils
+
+val internal_funs: ident list
+val arith_funs: ident list
+val bool_funs: ident list
+val rel_funs: ident list
+val eval_dim_env: (Dimension.dim_desc list -> Dimension.dim_desc) Env.t
+val is_homomorphic_fun: ident -> bool
+val is_internal_fun: ident -> Types.t list -> bool
+val is_expr_internal_fun: Lustre_types.expr -> bool
+val is_value_internal_fun: Machine_code_types.value_t -> bool
+val is_stateless_fun: ident -> bool
+
+val type_env: Types.t Env.t
+val clock_env: Clocks.t Env.t
+
+val partial_eval: ident -> Lustre_types.expr -> Lustre_types.expr option -> Lustre_types.expr_desc
diff --git a/src/causality.mli b/src/causality.mli
new file mode 100644
index 00000000..cebaffce
--- /dev/null
+++ b/src/causality.mli
@@ -0,0 +1,62 @@
+open Utils
+open Lustre_types
+
+type error =
+  | DataCycle of ident list list
+  (* multiple failed partitions at once *)
+  | NodeCycle of ident list
+
+exception Error of error
+
+val pp_error: Format.formatter -> error -> unit
+
+module NodeDep: sig
+  val dependence_graph: program_t -> IdentDepGraph.t
+  val filter_static_inputs: var_decl list -> expr list -> Dimension.t list
+end
+
+(* Look for cycles in a dependency graph *)
+module CycleDetection: sig
+  val check_cycles: IdentDepGraph.t -> unit
+end
+
+(* A module to sort dependencies among local variables when relying on clocked
+   declarations *)
+module VarClockDep: sig
+  val sort: var_decl list -> var_decl list
+end
+
+module ExprDep: sig
+  (* instance vars represent node instance calls, they are not part of the
+     program/schedule, but used to simplify causality analysis *)
+  val mk_instance_var: ident -> ident
+  val is_instance_var: ident -> bool
+  val is_ghost_var: ident -> bool
+  val undo_instance_var: ident -> ident
+  val node_eq_equiv: node_desc -> (ident, ident) Hashtbl.t
+  val node_input_variables: node_desc -> ISet.t
+end
+
+(* Module used to compute static disjunction of variables based upon their
+   clocks. *)
+module Disjunction: sig
+  module CISet: Set.S with type elt = var_decl
+
+  (* map: var |-> list of disjoint vars, sorted in increasing branch length
+     order, maybe removing shorter branches *)
+  type disjoint_map = (ident, CISet.t) Hashtbl.t
+
+  val clock_disjoint_map: var_decl list -> disjoint_map
+end
+
+(* Tests whether [v] is a root of graph [g], i.e. a source *)
+val is_graph_root: ident -> IdentDepGraph.t -> bool
+
+(* Computes the set of graph roots, i.e. the sources of acyclic graph [g] *)
+val graph_roots: IdentDepGraph.t -> ident list
+
+(* Takes a node and return a pair (node', graph) where node' is node rebuilt
+   with the equations enriched with new ones introduced to "break cycles" *)
+val global_dependency: node_desc -> node_desc * IdentDepGraph.t
+
+val pp_dep_graph: Format.formatter -> IdentDepGraph.t -> unit
diff --git a/src/checks/access.mli b/src/checks/access.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/checks/algebraicLoop.mli b/src/checks/algebraicLoop.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/checks/init_calculus.mli b/src/checks/init_calculus.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/checks/liveness.ml b/src/checks/liveness.ml
index 3db48059..dea8fd0c 100644
--- a/src/checks/liveness.ml
+++ b/src/checks/liveness.ml
@@ -21,6 +21,8 @@ type context = {
   policy : (ident, var_decl) Hashtbl.t;
 }
 
+type fanin = (ident, tag) Hashtbl.t
+
 (* computes the in-degree for each local variable of node [n], according to dep
    graph [g]. *)
 let compute_fanin n g =
diff --git a/src/checks/liveness.mli b/src/checks/liveness.mli
new file mode 100644
index 00000000..e6078ad6
--- /dev/null
+++ b/src/checks/liveness.mli
@@ -0,0 +1,18 @@
+open Utils
+open Lustre_types
+
+val compute_unused_variables: node_desc -> IdentDepGraph.t -> ISet.t
+
+type fanin = (ident, tag) Hashtbl.t
+
+ (* computes the in-degree for each local variable of node [n], according to dep
+   graph [g]. *)
+val compute_fanin: node_desc -> IdentDepGraph.t -> fanin
+
+val pp_fanin: Format.formatter -> fanin -> unit
+
+val compute_reuse_policy: node_desc -> ident list list ->
+  Causality.Disjunction.disjoint_map -> IdentDepGraph.t -> (ident, var_decl) Hashtbl.t
+
+(* replace variable [v] by [v'] in graph [g]. [v'] is a dead variable *)
+val replace_in_dep_graph: ident -> ident -> IdentDepGraph.t -> unit
diff --git a/src/checks/stateless.ml b/src/checks/stateless.ml
index 3d4cc7b3..32c67717 100644
--- a/src/checks/stateless.ml
+++ b/src/checks/stateless.ml
@@ -9,6 +9,7 @@
 (*                                                                  *)
 (********************************************************************)
 
+open Utils
 open Lustre_types
 open Corelang
 
diff --git a/src/checks/stateless.mli b/src/checks/stateless.mli
new file mode 100644
index 00000000..33f466d3
--- /dev/null
+++ b/src/checks/stateless.mli
@@ -0,0 +1,16 @@
+open Utils
+open Lustre_types
+
+type error =
+  | Stateful_kwd of ident
+  | Stateful_imp of ident
+  | Stateful_ext_C of ident
+
+exception Error of Location.t * error
+
+val check_node: top_decl -> bool
+val check_prog: program_t -> unit
+val force_prog: program_t -> unit
+val check_compat: top_decl list -> unit
+
+val pp_error: Format.formatter -> error -> unit
diff --git a/src/clock_calculus.ml b/src/clock_calculus.ml
index 9cb97068..05b45a75 100644
--- a/src/clock_calculus.ml
+++ b/src/clock_calculus.ml
@@ -596,7 +596,7 @@ and clock_expr env expr =
   in
   Log.report ~level:4 (fun fmt ->
       Format.fprintf fmt "Clock of expr %a: %a@ " Printers.pp_expr expr
-        Clocks.print_ck resulting_ck);
+        Clocks.pp resulting_ck);
   resulting_ck
 
 let clock_of_vlist vars =
@@ -684,7 +684,7 @@ let clock_node env loc nd =
   let ck_node = new_ck (Carrow (ck_ins, ck_outs)) false in
   unify_imported_clock None ck_node loc;
   Log.report ~level:3 (fun fmt ->
-      Format.fprintf fmt "Clock of %s: %a@ " nd.node_id print_ck ck_node);
+      Format.fprintf fmt "Clock of %s: %a@ " nd.node_id Clocks.pp ck_node);
   (* Local variables may contain first-order carrier variables that should be
      generalized. That's not the case for types. *)
   try_generalize ck_node loc;
@@ -697,7 +697,7 @@ let clock_node env loc nd =
   (* if (is_main && is_polymorphic ck_node) then raise (Error
      (loc,(Cannot_be_polymorphic ck_node))); *)
   Log.report ~level:3 (fun fmt ->
-      Format.fprintf fmt "Generalized clock of %s: %a@ @ " nd.node_id print_ck
+      Format.fprintf fmt "Generalized clock of %s: %a@ @ " nd.node_id Clocks.pp
         ck_node);
   nd.node_clock <- ck_node;
   Env.add_value env nd.node_id ck_node
@@ -776,7 +776,7 @@ let uneval_vdecl_generics vdecl =
   if Types.get_clock_base_type vdecl.var_type <> None then
     match get_carrier_name vdecl.var_clock with
     | None ->
-      Format.eprintf "internal error: %a@." print_ck vdecl.var_clock;
+      Format.eprintf "internal error: %a@." Clocks.pp vdecl.var_clock;
       assert false
     | Some cr ->
       Clocks.uneval vdecl.var_id cr
@@ -803,7 +803,7 @@ let check_env_compat header declared computed =
         let computed_c =
           instantiate (ref []) (ref []) (Env.lookup_value computed k)
         in
-        try_semi_unify decl_clock_k computed_c Location.dummy_loc
+        try_semi_unify decl_clock_k computed_c Location.dummy
       with Not_found ->
         (* If the lookup failed then either an actual required element should
            have been declared and is missing but typing should have catch it, or
diff --git a/src/clock_calculus.mli b/src/clock_calculus.mli
new file mode 100644
index 00000000..2a57b425
--- /dev/null
+++ b/src/clock_calculus.mli
@@ -0,0 +1,9 @@
+open Lustre_types
+
+val clock_node: Clocks.t Env.t -> Location.t -> node_desc -> Clocks.t Env.t
+
+val compute_root_clock: Clocks.t -> Clocks.t
+
+val clock_prog: Clocks.t Env.t -> program_t -> Clocks.t Env.t
+
+val check_env_compat: top_decl list -> Clocks.t Env.t -> Clocks.t Env.t -> unit
diff --git a/src/clock_predef.mli b/src/clock_predef.mli
new file mode 100644
index 00000000..5558c9fa
--- /dev/null
+++ b/src/clock_predef.mli
@@ -0,0 +1,4 @@
+val ck_nullary_univ: Clocks.t
+val ck_unary_univ: Clocks.t
+val ck_bin_univ: Clocks.t
+val ck_tuple: Clocks.t list -> Clocks.t
diff --git a/src/clocks.ml b/src/clocks.ml
index 5290af2b..046693f8 100644
--- a/src/clocks.ml
+++ b/src/clocks.ml
@@ -36,7 +36,7 @@ and carrier_expr = {
   carrier_id : int;
 }
 
-type clock_expr = {
+type t = {
   mutable cdesc : clock_desc;
   mutable cscoped : bool;
   cid : int;
@@ -44,41 +44,41 @@ type clock_expr = {
 
 (* pck stands for periodic clock. Easier not to separate pck from other clocks *)
 and clock_desc =
-  | Carrow of clock_expr * clock_expr
-  | Ctuple of clock_expr list
-  | Con of clock_expr * carrier_expr * ident
-  (* | Pck_up of clock_expr * int *)
-  (* | Pck_down of clock_expr * int *)
-  (* | Pck_phase of clock_expr * rat *)
+  | Carrow of t * t
+  | Ctuple of t list
+  | Con of t * carrier_expr * ident
+  (* | Pck_up of t * int *)
+  (* | Pck_down of t * int *)
+  (* | Pck_phase of t * rat *)
   (* | Pck_const of int * rat *)
   | Cvar (* of clock_set *)
   (* Monomorphic clock variable *)
   | Cunivar
   (* of clock_set *)
   (* Polymorphic clock variable *)
-  | Clink of clock_expr
+  | Clink of t
   (* During unification, make links instead of substitutions *)
-  | Ccarrying of carrier_expr * clock_expr
+  | Ccarrying of carrier_expr * t
 
 type error =
-  | Clock_clash of clock_expr * clock_expr
+  | Clock_clash of t * t
   (* | Not_pck *)
-  (* | Clock_set_mismatch of clock_expr * clock_set *)
-  | Cannot_be_polymorphic of clock_expr
-  | Invalid_imported_clock of clock_expr
-  | Invalid_const of clock_expr
+  (* | Clock_set_mismatch of t * clock_set *)
+  | Cannot_be_polymorphic of t
+  | Invalid_imported_clock of t
+  | Invalid_const of t
   | Factor_zero
   | Carrier_mismatch of carrier_expr * carrier_expr
-  | Carrier_extrusion of clock_expr * carrier_expr
-  | Clock_extrusion of clock_expr * clock_expr
+  | Carrier_extrusion of t * carrier_expr
+  | Clock_extrusion of t * t
 
-exception Unify of clock_expr * clock_expr
+exception Unify of t * t
 
 exception Mismatch of carrier_expr * carrier_expr
 
 exception Scope_carrier of carrier_expr
 
-exception Scope_clock of clock_expr
+exception Scope_clock of t
 
 exception Error of Location.t * error
 
@@ -102,7 +102,8 @@ let rec print_ck_long fmt ck =
   | Carrow (ck1, ck2) ->
     fprintf fmt "%a -> %a" print_ck_long ck1 print_ck_long ck2
   | Ctuple cklist ->
-    fprintf fmt "(%a)" (fprintf_list ~sep:" * " print_ck_long) cklist
+    fprintf fmt "(%a)" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt " * ")
+                          print_ck_long) cklist
   | Con (ck, c, l) ->
     fprintf fmt "%a on %s(%a)" print_ck_long ck l print_carrier c
   | Cvar ->
@@ -283,7 +284,7 @@ let eq_carrier cr1 cr2 =
   | _ ->
     cr1.carrier_id = cr2.carrier_id
 
-let eq_clock ck1 ck2 = (repr ck1).cid = (repr ck2).cid
+let equal ck1 ck2 = (repr ck1).cid = (repr ck2).cid
 
 (* Returns the clock root of a clock *)
 let rec root ck =
@@ -335,7 +336,7 @@ let rec disjoint_branches br1 br2 =
 
 (* Disjunction relation between variables based upon their static clocks. *)
 let disjoint ck1 ck2 =
-  eq_clock (root ck1) (root ck2) && disjoint_branches (branch ck1) (branch ck2)
+  equal (root ck1) (root ck2) && disjoint_branches (branch ck1) (branch ck2)
 
 let print_cvar fmt cvar =
   match cvar.cdesc with
@@ -350,13 +351,13 @@ let print_cvar fmt cvar =
 
 (* Nice pretty-printing. Simplifies expressions before printing them. Non-linear
    complexity. *)
-let print_ck fmt ck =
+let pp fmt ck =
   let rec aux fmt ck =
     match ck.cdesc with
     | Carrow (ck1, ck2) ->
       fprintf fmt "%a -> %a" aux ck1 aux ck2
     | Ctuple cklist ->
-      fprintf fmt "(%a)" (fprintf_list ~sep:" * " aux) cklist
+      fprintf fmt "(%a)" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt " * ") aux) cklist
     | Con (ck, c, l) ->
       fprintf fmt "%a on %s(%a)" aux ck l print_carrier c
     | Cvar ->
@@ -373,50 +374,50 @@ let print_ck fmt ck =
   let cvars = constrained_vars_of_clock ck in
   aux fmt ck;
   if cvars <> [] then
-    fprintf fmt " (where %a)" (fprintf_list ~sep:", " print_cvar) cvars
+    fprintf fmt " (where %a)" (pp_comma_list print_cvar) cvars
 
 (* prints only the Con components of a clock, useful for printing nodes *)
-let rec print_ck_suffix fmt ck =
+let rec pp_suffix fmt ck =
   match ck.cdesc with
   | Carrow _ | Ctuple _ | Cvar | Cunivar ->
     ()
   | Con (ck, c, l) ->
-    if !Options.kind2_print then print_ck_suffix fmt ck
-    else fprintf fmt "%a when %s(%a)" print_ck_suffix ck l print_carrier c
+    if !Options.kind2_print then pp_suffix fmt ck
+    else fprintf fmt "%a when %s(%a)" pp_suffix ck l print_carrier c
   | Clink ck' ->
-    print_ck_suffix fmt ck'
+    pp_suffix fmt ck'
   | Ccarrying (_, ck') ->
-    fprintf fmt "%a" print_ck_suffix ck'
+    fprintf fmt "%a" pp_suffix ck'
 
 let pp_error fmt = function
   | Clock_clash (ck1, ck2) ->
     reset_names ();
-    fprintf fmt "Expected clock %a, got clock %a@." print_ck ck1 print_ck ck2
+    fprintf fmt "Expected clock %a, got clock %a@." pp ck1 pp ck2
   | Carrier_mismatch (cr1, cr2) ->
     fprintf fmt "Name clash. Expected clock %a, got clock %a@." print_carrier
       cr1 print_carrier cr2
   | Cannot_be_polymorphic ck ->
     reset_names ();
-    fprintf fmt "The main node cannot have a polymorphic clock: %a@." print_ck
+    fprintf fmt "The main node cannot have a polymorphic clock: %a@." pp
       ck
   | Invalid_imported_clock ck ->
     reset_names ();
-    fprintf fmt "Not a valid imported node clock: %a@." print_ck ck
+    fprintf fmt "Not a valid imported node clock: %a@." pp ck
   | Invalid_const ck ->
     reset_names ();
-    fprintf fmt "Clock %a is not a valid periodic clock@." print_ck ck
+    fprintf fmt "Clock %a is not a valid periodic clock@." pp ck
   | Factor_zero ->
     fprintf fmt "Cannot apply clock transformation with factor 0@."
   | Carrier_extrusion (ck, cr) ->
     fprintf fmt
       "This node has clock@.%a@.It is invalid as the carrier %a escapes its \
        scope@."
-      print_ck ck print_carrier cr
+      pp ck print_carrier cr
   | Clock_extrusion (ck_node, ck) ->
     fprintf fmt
       "This node has clock@.%a@.It is invalid as the clock %a escapes its \
        scope@."
-      print_ck ck_node print_ck ck
+      pp ck_node pp ck
 
 let const_of_carrier cr =
   match (carrier_repr cr).carrier_desc with
diff --git a/src/clocks.mli b/src/clocks.mli
new file mode 100644
index 00000000..63f8688a
--- /dev/null
+++ b/src/clocks.mli
@@ -0,0 +1,97 @@
+open Utils
+
+(* Clock carriers basically correspond to the "c" in "x when c" *)
+type carrier_desc =
+  | Carry_const of ident
+  | Carry_name
+  | Carry_var
+  | Carry_link of carrier_expr
+
+(* Carriers are scoped, to detect clock extrusion. In other words, we check the
+   scope of a clock carrier before generalizing it. *)
+and carrier_expr = {
+  mutable carrier_desc : carrier_desc;
+  mutable carrier_scoped : bool;
+  carrier_id : int;
+}
+
+type t = {
+  mutable cdesc : clock_desc;
+  mutable cscoped : bool;
+  cid : int;
+}
+
+(* pck stands for periodic clock. Easier not to separate pck from other clocks *)
+and clock_desc =
+  | Carrow of t * t
+  | Ctuple of t list
+  | Con of t * carrier_expr * ident
+  | Cvar (* of clock_set *)
+  (* Monomorphic clock variable *)
+  | Cunivar
+  (* of clock_set *)
+  (* Polymorphic clock variable *)
+  | Clink of t
+  (* During unification, make links instead of substitutions *)
+  | Ccarrying of carrier_expr * t
+
+type error =
+  | Clock_clash of t * t
+  | Cannot_be_polymorphic of t
+  | Invalid_imported_clock of t
+  | Invalid_const of t
+  | Factor_zero
+  | Carrier_mismatch of carrier_expr * carrier_expr
+  | Carrier_extrusion of t * carrier_expr
+  | Clock_extrusion of t * t
+
+val pp: Format.formatter -> t -> unit
+val pp_suffix: Format.formatter -> t -> unit
+
+val new_var: bool -> t
+
+val new_univar: unit -> t
+
+val new_ck: clock_desc -> bool -> t
+
+val new_carrier: carrier_desc -> bool -> carrier_expr
+
+val bottom: t
+
+val repr: t -> t
+val carrier_repr: carrier_expr -> carrier_expr
+
+val simplify: t -> t
+
+val clock_on: t -> carrier_expr -> ident -> t
+
+val clock_of_clock_list: t list -> t
+val clock_list_of_clock: t -> t list
+
+val root: t -> t
+
+val branch: t -> (carrier_expr * ident) list
+
+val common_prefix: (carrier_expr * ident) list -> (carrier_expr * ident) list -> (carrier_expr * ident) list
+
+val clock_of_root_branch: t -> (carrier_expr * ident) list -> t
+
+val split_arrow: t -> t * t
+
+val clock_current: t -> t
+
+val uneval: ident -> carrier_expr -> unit
+
+val get_carrier_name: t -> carrier_expr option
+
+val equal: t -> t -> bool
+
+val const_of_carrier: carrier_expr -> ident
+
+val pp_error: Format.formatter -> error -> unit
+
+exception Unify of t * t
+exception Scope_carrier of carrier_expr
+exception Scope_clock of t
+exception Error of Location.t * error
+exception Mismatch of carrier_expr * carrier_expr
diff --git a/src/compiler_common.ml b/src/compiler_common.ml
index 8a0e6521..60269c47 100644
--- a/src/compiler_common.ml
+++ b/src/compiler_common.ml
@@ -16,9 +16,9 @@ open Corelang
 
 let check_main () =
   if !Options.main_node = "" then (
-    eprintf "Code generation error: %a@." Error.pp_error_msg
+    eprintf "Code generation error: %a@." Error.pp
       Error.No_main_specified;
-    raise (Error.Error (Location.dummy_loc, Error.No_main_specified)))
+    raise (Error.Error (Location.dummy, Error.No_main_specified)))
 
 let create_dest_dir () =
   if not (Sys.file_exists !Options.dest_dir) then (
@@ -58,7 +58,7 @@ let parse filename extension =
      *    Parse.report_error err;
      *    raise exc *)
     | Error.Error (loc, err) as exc ->
-      eprintf "Parsing error: %a%a@." Error.pp_error_msg err Location.pp_loc loc;
+      eprintf "Parsing error: %a%a@." Error.pp err Location.pp loc;
       raise exc
   in
   (* close_in f_in; *)
@@ -68,7 +68,7 @@ let expand_automata decls =
   Log.report ~level:1 (fun fmt -> fprintf fmt "@ .. expanding automata@ ");
   try Automata.expand_decls decls
   with Error.Error (loc, err) as exc ->
-    eprintf "Automata error: %a%a@." Error.pp_error_msg err Location.pp_loc loc;
+    eprintf "Automata error: %a%a@." Error.pp err Location.pp loc;
     raise exc
 
 let check_stateless_decls decls =
@@ -77,7 +77,7 @@ let check_stateless_decls decls =
   try Stateless.check_prog decls
   with Stateless.Error (loc, err) as exc ->
     eprintf "Stateless status error: %a%a@." Stateless.pp_error err
-      Location.pp_loc loc;
+      Location.pp loc;
     raise exc
 
 let force_stateful_decls decls =
@@ -85,7 +85,7 @@ let force_stateful_decls decls =
   try Stateless.force_prog decls
   with Stateless.Error (loc, err) as exc ->
     eprintf "Stateless status error: %a%a@." Stateless.pp_error err
-      Location.pp_loc loc;
+      Location.pp loc;
     raise exc
 
 let type_decls env decls =
@@ -93,7 +93,7 @@ let type_decls env decls =
   let new_env =
     try Typing.type_prog env decls
     with Types.Error (loc, err) as exc ->
-      eprintf "Typing error: %a%a@." Types.pp_error err Location.pp_loc loc;
+      eprintf "Typing error: %a%a@." Types.pp_error err Location.pp loc;
       raise exc
   in
   Log.report ~level:1 (fun fmt -> fprintf fmt "@]");
@@ -107,7 +107,7 @@ let clock_decls env decls =
   let new_env =
     try Clock_calculus.clock_prog env decls
     with Clocks.Error (loc, err) as exc ->
-      eprintf "Clock calculus error: %a%a@." Clocks.pp_error err Location.pp_loc
+      eprintf "Clock calculus error: %a%a@." Clocks.pp_error err Location.pp
         loc;
       raise exc
   in
@@ -154,19 +154,19 @@ let check_compatibility (_, computed_types_env, computed_clocks_env)
     eprintf
       "Type mismatch between computed type and declared type in lustre \
        interface file: %a%a@."
-      Types.pp_error err Location.pp_loc loc;
+      Types.pp_error err Location.pp loc;
     raise exc
   | Clocks.Error (loc, err) as exc ->
     eprintf
       "Clock mismatch between computed clock and declared clock in lustre \
        interface file: %a%a@."
-      Clocks.pp_error err Location.pp_loc loc;
+      Clocks.pp_error err Location.pp loc;
     raise exc
   | Stateless.Error (loc, err) as exc ->
     eprintf
       "Stateless status mismatch between defined status and declared status in \
        lustre interface file: %a%a@."
-      Stateless.pp_error err Location.pp_loc loc;
+      Stateless.pp_error err Location.pp loc;
     raise exc
 
 (* Process each node/imported node and introduce the associated contract node *)
diff --git a/src/compiler_common.mli b/src/compiler_common.mli
new file mode 100644
index 00000000..89d9d3d0
--- /dev/null
+++ b/src/compiler_common.mli
@@ -0,0 +1,13 @@
+open Lustre_types
+
+val check_main: unit -> unit
+
+(* Loading Lus/Lusi file and filling type tables with parsed functions/nodes *)
+val parse: string -> string -> program_t
+
+val check_compatibility: program_t * Types.t Env.t * Clocks.t Env.t ->
+  top_decl list * Types.t Env.t * Clocks.t Env.t -> unit
+
+val update_vdecl_parents_prog: program_t -> unit
+
+val expand_automata: program_t -> program_t
diff --git a/src/compiler_stages.ml b/src/compiler_stages.ml
index 7ce0503b..b3bb823b 100644
--- a/src/compiler_stages.ml
+++ b/src/compiler_stages.ml
@@ -6,7 +6,8 @@ module Mpfr = Lustrec_mpfr
 exception StopPhase1 of program_t
 
 let dynamic_checks () =
-  match !Options.output, !Options.spec with "C", "C" -> true | _ -> false
+  let open Options in
+  match !output, !spec with OutC, SpecC -> true | _ -> false
 
 let generate_c_header = ref false
 
@@ -36,7 +37,7 @@ let compile_source_to_header prog computed_types_env computed_clocks_env dirname
       (* is it a lusi file ? *)
       (if from_lusi then prog else Lusic.extract_header dirname basename prog)
       destname lusic_ext;
-    generate_c_header := !Options.output = "C")
+    generate_c_header := !Options.output = Options.OutC)
   else (
     (* Lusic exists and is usable. Checking compatibility *)
     Log.report ~level:1 (fun fmt ->
diff --git a/src/compiler_stages.mli b/src/compiler_stages.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/corelang.ml b/src/corelang.ml
index fabbe47f..2c8097f2 100644
--- a/src/corelang.ml
+++ b/src/corelang.ml
@@ -9,6 +9,7 @@
 (*                                                                  *)
 (********************************************************************)
 
+open Utils
 open Format
 open Lustre_types
 open Machine_code_types
@@ -35,7 +36,7 @@ with type elt = var_decl = struct
 
   let pp fmt s =
     Format.fprintf fmt "{@[%a}@]"
-      (Utils.fprintf_list ~sep:",@ " Printers.pp_var)
+      (pp_comma_list Printers.pp_var)
       (elements s)
 
   (* Strangley the find_first function of Set.Make is incorrect (at the current
@@ -44,10 +45,10 @@ with type elt = var_decl = struct
 end
 
 let dummy_type_dec =
-  { ty_dec_desc = Tydec_any; ty_dec_loc = Location.dummy_loc }
+  { ty_dec_desc = Tydec_any; ty_dec_loc = Location.dummy }
 
 let dummy_clock_dec =
-  { ck_dec_desc = Ckdec_any; ck_dec_loc = Location.dummy_loc }
+  { ck_dec_desc = Ckdec_any; ck_dec_loc = Location.dummy }
 
 (************************************************************)
 (* *)
@@ -83,7 +84,7 @@ let dummy_var_decl name typ =
     var_parent_nodeid = None;
     var_type = typ;
     var_clock = Clocks.new_ck Clocks.Cvar true;
-    var_loc = Location.dummy_loc;
+    var_loc = Location.dummy;
   }
 
 let mkexpr loc d =
@@ -192,7 +193,7 @@ let empty_contract =
     guarantees = [];
     modes = [];
     imports = [];
-    spec_loc = Location.dummy_loc;
+    spec_loc = Location.dummy;
   }
 
 (* For const declaration we do as for regular lustre node. But for local flows
@@ -373,7 +374,7 @@ let is_contract td =
 
 (* alias and type definition table *)
 
-let mktop = mktop_decl Location.dummy_loc !Options.dest_dir false
+let mktop = mktop_decl Location.dummy !Options.dest_dir false
 
 let top_int_type = mktop (TypeDef { tydef_id = "int"; tydef_desc = Tydec_int })
 
@@ -440,7 +441,7 @@ let rec coretype_equal ty1 ty2 =
     | Tydec_clock ty1, Tydec_clock ty2 ->
       coretype_equal ty1 ty2
     | Tydec_array (d1, ty1), Tydec_array (d2, ty2) ->
-      Dimension.is_eq_dimension d1 d2 && coretype_equal ty1 ty2
+      Dimension.equal d1 d2 && coretype_equal ty1 ty2
     | Tydec_enum tl1, Tydec_enum tl2 ->
       List.sort compare tl1 = List.sort compare tl2
     | Tydec_struct fl1, Tydec_struct fl2 ->
@@ -628,7 +629,7 @@ let rec expr_of_dimension dim =
       expr_of_dimension dim'
     | Dvar | Dunivar ->
       Format.eprintf "internal error: Corelang.expr_of_dimension %a@."
-        Dimension.pp_dimension dim;
+        Dimension.pp dim;
       assert false
   in
   { expr with expr_type = Types.new_ty Types.type_int }
@@ -1195,19 +1196,19 @@ let pp_decl_clock fmt cdecl =
   | Node nd ->
     fprintf fmt "%s: " nd.node_id;
     Utils.reset_names ();
-    fprintf fmt "%a@ " Clocks.print_ck nd.node_clock
+    fprintf fmt "%a@ " Clocks.pp nd.node_clock
   | ImportedNode ind ->
     fprintf fmt "%s: " ind.nodei_id;
     Utils.reset_names ();
-    fprintf fmt "%a@ " Clocks.print_ck ind.nodei_clock
+    fprintf fmt "%a@ " Clocks.pp ind.nodei_clock
   | Const _ | Include _ | Open _ | TypeDef _ ->
     ()
 
-let pp_prog_clock fmt prog = Utils.fprintf_list ~sep:"" pp_decl_clock fmt prog
+let pp_prog_clock fmt prog = pp_print_list ~pp_sep:pp_print_nothing pp_decl_clock fmt prog
 
 (* filling node table with internal functions *)
 let vdecls_of_typ_ck cpt ty =
-  let loc = Location.dummy_loc in
+  let loc = Location.dummy in
   List.map
     (fun _ ->
       incr cpt;
@@ -1399,7 +1400,7 @@ let get_expr_vars e =
   let rec get_expr_vars vars e = get_expr_desc_vars vars e.expr_desc
   and get_expr_desc_vars vars expr_desc =
     (*Format.eprintf "get_expr_desc_vars expr=%a@." Printers.pp_expr (mkexpr
-      Location.dummy_loc expr_desc);*)
+      Location.dummy expr_desc);*)
     match expr_desc with
     | Expr_const _ ->
       vars
@@ -1512,7 +1513,7 @@ let find_eq xl eqs =
     match eqs with
     | [] ->
       Format.eprintf "Looking for variables %a in the following equations@.%a@."
-        (Utils.fprintf_list ~sep:" , " (fun fmt v -> Format.fprintf fmt "%s" v))
+        (pp_comma_list (fun fmt v -> Format.fprintf fmt "%s" v))
         xl Printers.pp_node_eqs eqs;
       assert false
     | hd :: tl ->
diff --git a/src/corelang.mli b/src/corelang.mli
index 8dea180d..43bc642c 100644
--- a/src/corelang.mli
+++ b/src/corelang.mli
@@ -8,7 +8,7 @@
 (*  version 2.1.                                                    *)
 (*                                                                  *)
 (********************************************************************)
-
+open Utils
 open Lustre_types
 
 module VDeclModule : sig
@@ -16,7 +16,7 @@ module VDeclModule : sig
 
   val compare : t -> t -> int
 end
-with type t = Lustre_types.var_decl
+with type t = var_decl
 
 module VSet : sig
   include Set.S
@@ -25,7 +25,7 @@ module VSet : sig
 
   val get : ident -> t -> elt
 end
-with type elt = Lustre_types.var_decl
+with type elt = var_decl
 
 val dummy_type_dec : type_dec
 
@@ -48,7 +48,7 @@ val mkvar_decl :
   (* parent id *) ->
   var_decl
 
-val dummy_var_decl : ident -> Types.type_expr -> var_decl
+val dummy_var_decl : ident -> Types.t -> var_decl
 
 val var_decl_of_const : ?parentid:ident option -> const_desc -> var_decl
 
@@ -182,11 +182,11 @@ val expr_of_expr_list : Location.t -> expr list -> expr
 
 val call_of_expr : expr -> ident * expr list * expr option
 
-val expr_of_dimension : Dimension.dim_expr -> expr
+val expr_of_dimension : Dimension.t -> expr
 
-val dimension_of_expr : expr -> Dimension.dim_expr
+val dimension_of_expr : expr -> Dimension.t
 
-val dimension_of_const : Location.t -> constant -> Dimension.dim_expr
+val dimension_of_const : Location.t -> constant -> Dimension.t
 
 val expr_to_eexpr : expr -> eexpr
 (* REMOVED, pushed in utils.ml val new_tag : unit -> tag *)
@@ -222,7 +222,7 @@ val get_node : ident -> program_t -> node_desc
 (** Returns the node named ident in the provided program. Raise Not_found *)
 
 val rename_static :
-  (ident -> Dimension.dim_expr) -> type_dec_desc -> type_dec_desc
+  (ident -> Dimension.t) -> type_dec_desc -> type_dec_desc
 
 val rename_carrier : (ident -> ident) -> clock_dec_desc -> clock_dec_desc
 
@@ -296,8 +296,8 @@ val reset_cpt_fresh : unit -> unit
 val mk_fresh_var :
   ident * var_decl list ->
   Location.t ->
-  Types.type_expr ->
-  Clocks.clock_expr ->
+  Types.t ->
+  Clocks.t ->
   var_decl
 
 val find_eq : ident list -> eq list -> eq * eq list
diff --git a/src/delay.ml b/src/delay.ml
index 2e238256..bd257c6b 100644
--- a/src/delay.ml
+++ b/src/delay.ml
@@ -13,21 +13,21 @@ open Utils
 (** Types definitions and a few utility functions on delay types. Delay analysis
     by type polymorphism instead of constraints *)
 
-type delay_expr = { mutable ddesc : delay_desc; did : int }
+type t = { mutable ddesc : delay_desc; did : int }
 
 and delay_desc =
   | Dvar (* Monomorphic type variable *)
   | Dundef
-  | Darrow of delay_expr * delay_expr
-  | Dtuple of delay_expr list
-  | Dlink of delay_expr
+  | Darrow of t * t
+  | Dtuple of t list
+  | Dlink of t
   (* During unification, make links instead of substitutions *)
   | Dunivar
 (* Polymorphic type variable *)
 
-type error = Delay_clash of delay_expr * delay_expr
+type error = Delay_clash of t * t
 
-exception Unify of delay_expr * delay_expr
+exception Unify of t * t
 
 exception Error of Location.t * error
 
@@ -55,7 +55,7 @@ let split_arrow de =
     failwith "Internal error: not an arrow type"
 
 (** Returns the type corresponding to a type list. *)
-let delay_of_delay_list de =
+let of_delay_list de =
   if List.length de > 1 then new_delay (Dtuple de) else List.hd de
 
 (** [is_polymorphic de] returns true if [de] is polymorphic. *)
@@ -75,25 +75,26 @@ let rec is_polymorphic de =
     true
 
 (* Pretty-print*)
-open Format
+open Utils.Format
 
-let rec print_delay fmt de =
+let rec pp fmt de =
   match de.ddesc with
   | Dvar ->
     fprintf fmt "'_%s" (name_of_type de.did)
   | Dundef ->
     fprintf fmt "1"
   | Darrow (de1, de2) ->
-    fprintf fmt "%a->%a" print_delay de1 print_delay de2
+    fprintf fmt "%a->%a" pp de1 pp de2
   | Dtuple delist ->
-    fprintf fmt "(%a)" (Utils.fprintf_list ~sep:"*" print_delay) delist
+    fprintf fmt "(%a)" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt "*")
+                          pp) delist
   | Dlink de ->
-    print_delay fmt de
+    pp fmt de
   | Dunivar ->
     fprintf fmt "'%s" (name_of_delay de.did)
 
 let pp_error fmt = function
   | Delay_clash (de1, de2) ->
     Utils.reset_names ();
-    fprintf fmt "Expected delay %a, got delay %a@." print_delay de1 print_delay
+    fprintf fmt "Expected delay %a, got delay %a@." pp de1 pp
       de2
diff --git a/src/delay.mli b/src/delay.mli
new file mode 100644
index 00000000..d5132c7a
--- /dev/null
+++ b/src/delay.mli
@@ -0,0 +1,17 @@
+type t = { mutable ddesc : delay_desc; did : int }
+
+and delay_desc =
+  | Dvar (* Monomorphic type variable *)
+  | Dundef
+  | Darrow of t * t
+  | Dtuple of t list
+  | Dlink of t
+  (* During unification, make links instead of substitutions *)
+  | Dunivar
+(* Polymorphic type variable *)
+
+val new_var: unit -> t
+
+val new_univar: unit -> t
+
+val new_delay: delay_desc -> t
diff --git a/src/delay_predef.mli b/src/delay_predef.mli
new file mode 100644
index 00000000..8f323305
--- /dev/null
+++ b/src/delay_predef.mli
@@ -0,0 +1,4 @@
+val delay_nullary_poly_op: Delay.t
+val delay_unary_poly_op: Delay.t
+val delay_binary_poly_op: Delay.t
+val delay_ternary_poly_op: Delay.t
diff --git a/src/dune b/src/dune
index 10452d91..accc80f7 100644
--- a/src/dune
+++ b/src/dune
@@ -8,6 +8,7 @@
 (library
  (name lustrec_interface)
  (package lustrec)
+ (modules_without_implementation scheduling_type machine_code_types)
  (modules
   lustre_types
   utils
@@ -21,11 +22,11 @@
   version
   clocks
   delay
+  scheduling_type
   machine_code_types
   spec_types
   spec_common
   lustre_live
-  scheduling_type
   log
   printers
   corelang
diff --git a/src/error.ml b/src/error.ml
index 657b616a..fd35e33a 100644
--- a/src/error.ml
+++ b/src/error.ml
@@ -1,8 +1,7 @@
+open Utils
 open Format
 
-type ident = Lustre_types.ident
-
-type error_kind =
+type t =
   | Main_not_found
   | Main_wrong_kind
   | No_main_specified
@@ -13,7 +12,7 @@ type error_kind =
   | AlgebraicLoop
   | LoadError of string
 
-exception Error of Location.t * error_kind
+exception Error of Location.t * t
 
 let return_code kind =
   match kind with
@@ -36,7 +35,7 @@ let return_code kind =
   | LoadError _ ->
     10
 
-let pp_error_msg fmt = function
+let pp fmt = function
   | Main_not_found ->
     fprintf fmt "Could not find the definition of main node %s.@."
       !Global.main_node
@@ -66,7 +65,7 @@ let pp_error_msg fmt = function
     fprintf fmt "Load error: %s.@." l
 
 let pp_warning loc pp_msg =
-  Format.eprintf "%a@.Warning: %t@." Location.pp_loc loc pp_msg
+  Format.eprintf "%a@.Warning: %t@." Location.pp loc pp_msg
 
 let pp_error loc pp_msg =
-  Format.eprintf "@.%a@.Error: @[<v 0>%t@]@.@?" Location.pp_loc loc pp_msg
+  Format.eprintf "@.%a@.Error: @[<v 0>%t@]@.@?" Location.pp loc pp_msg
diff --git a/src/error.mli b/src/error.mli
new file mode 100644
index 00000000..5adf214a
--- /dev/null
+++ b/src/error.mli
@@ -0,0 +1,18 @@
+open Utils
+
+type t =
+  | Main_not_found
+  | Main_wrong_kind
+  | No_main_specified
+  | Unbound_symbol of ident
+  | Already_bound_symbol of ident
+  | Unknown_library of ident
+  | Wrong_number of ident
+  | AlgebraicLoop
+  | LoadError of string
+
+exception Error of Location.t * t
+
+val pp: Format.formatter -> t -> unit
+val pp_error: Location.t -> (Format.formatter -> unit) -> unit
+val pp_warning: Location.t -> (Format.formatter -> unit) -> unit
diff --git a/src/expand.mli b/src/expand.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/features/machine_types/machine_types.ml b/src/features/machine_types/machine_types.ml
index c7e6d538..25d82ca4 100644
--- a/src/features/machine_types/machine_types.ml
+++ b/src/features/machine_types/machine_types.ml
@@ -177,7 +177,7 @@ 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
+  type type_expr = MTypes.t
 
   let map_type_basic f_basic =
     let rec map_type_basic e =
@@ -281,7 +281,7 @@ 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 =
+let machine_type_table : (var_decl, MTypes.t) Hashtbl.t =
   Hashtbl.create 13
 
 (* Store the node signatures, with machine types when available *)
@@ -336,7 +336,7 @@ let pp_c_var_type fmt v =
 
 let erroneous_annotation loc =
   Format.eprintf "Invalid annotation for machine_type at loc %a@."
-    Location.pp_loc loc;
+    Location.pp loc;
   assert false
 
 let valid_subtype subtype typ =
diff --git a/src/global.ml b/src/global.ml
index 95cc5a64..d9c43e37 100644
--- a/src/global.ml
+++ b/src/global.ml
@@ -1,9 +1,7 @@
-module Types = Types.Main
-
-let type_env : Types.type_expr Env.t ref = ref Env.initial
+let type_env : Types.t Env.t ref = ref Env.initial
 (* Basic_library.type_env *)
 
-let clock_env : Clocks.clock_expr Env.t ref = ref Env.initial
+let clock_env : Clocks.t Env.t ref = ref Env.initial
 (*Basic_library.clock_env *)
 
 let basename = ref ""
@@ -17,7 +15,7 @@ module TypeEnv = struct
 
   let iter f = Env.iter !type_env f
 
-  let pp pp_fun fmt () = Env.pp_env pp_fun fmt !type_env
+  let pp pp_fun fmt () = Env.pp pp_fun fmt !type_env
 end
 
 let initialize () = main_node := !Options.main_node
diff --git a/src/global.mli b/src/global.mli
new file mode 100644
index 00000000..e5e0e45e
--- /dev/null
+++ b/src/global.mli
@@ -0,0 +1,3 @@
+val type_env: Types.t Env.t ref
+val clock_env: Clocks.t Env.t ref
+val main_node: string ref
diff --git a/src/init_predef.mli b/src/init_predef.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/inliner.ml b/src/inliner.ml
index fb31a3de..bfa3507d 100644
--- a/src/inliner.ml
+++ b/src/inliner.ml
@@ -375,7 +375,7 @@ let inline_all_calls node nodes =
   { node with top_decl_desc = Node (inline_node nd nodes) }
 
 let witness filename main_name orig inlined (* type_env clock_env *) =
-  let loc = Location.dummy_loc in
+  let loc = Location.dummy in
   let rename_local_node nodes prefix id =
     if List.exists (check_node_name id) nodes then prefix ^ id else id
   in
@@ -551,13 +551,12 @@ let pp_inline_calls fmt prog =
   let nodes_with_anns =
     List.fold_left (fun accu (k, _) -> ISet.add k accu) ISet.empty local_anns
   in
-  Format.fprintf fmt "@[<v 0>Inlined expresssions in node (by tags):@ %a@]"
-    (fprintf_list ~sep:"" (fun fmt top ->
+  Format.(fprintf fmt "@[<v 0>Inlined expresssions in node (by tags):@ %a@]"
+    (pp_print_list ~pp_sep:pp_print_nothing (fun fmt top ->
          match top.top_decl_desc with
          | Node nd when ISet.mem nd.node_id nodes_with_anns ->
-           Format.fprintf fmt "%s: {@[<v 0>%a}@]@ " nd.node_id
-             (fprintf_list ~sep:"@ " (fun fmt tag ->
-                  Format.fprintf fmt "%i" tag))
+           fprintf fmt "%s: {@[<v 0>%a}@]@ " nd.node_id
+             (pp_print_list pp_print_int)
              (List.fold_left
                 (fun accu (id, tag) ->
                   if id = nd.node_id then tag :: accu else accu)
@@ -565,7 +564,7 @@ let pp_inline_calls fmt prog =
          (* | Node nd -> Format.fprintf fmt "%s: no inline annotations"
             nd.node_id *)
          | _ ->
-           ()))
+           ())))
     prog
 
 let local_inline prog (* type_env clock_env *) =
diff --git a/src/inliner.mli b/src/inliner.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/log.ml b/src/log.ml
index 8a651f30..8acc242a 100644
--- a/src/log.ml
+++ b/src/log.ml
@@ -9,9 +9,9 @@
 (*                                                                  *)
 (********************************************************************)
 
-let report ?plugin:(modulename = "") ?(verbose_level = Options.verbose_level)
+let report ?plugin:(modulename = "") ?(verbose_level = (fun () -> !Options.verbose_level) ())
     ~level p =
-  if !verbose_level >= level then
+  if verbose_level >= level then
     if modulename = "" then Format.eprintf "%t" p
     else Format.eprintf "[%s] @[%t@]" modulename p
 
diff --git a/src/log.mli b/src/log.mli
new file mode 100644
index 00000000..3a728392
--- /dev/null
+++ b/src/log.mli
@@ -0,0 +1 @@
+val report: ?plugin:string -> ?verbose_level:int -> level:int -> (Format.formatter -> unit) -> unit
diff --git a/src/lusic.ml b/src/lusic.ml
index 0ecdc255..0cf9d661 100644
--- a/src/lusic.ml
+++ b/src/lusic.ml
@@ -15,7 +15,7 @@ open Lustre_types
 (* Lusic to/from Header Printing functions *)
 (********************************************************************************************)
 
-type lusic = { obsolete : bool; from_lusi : bool; contents : top_decl list }
+type t = { obsolete : bool; from_lusi : bool; contents : program_t }
 
 (* extracts a header from a program representing module owner = dirname/basename *)
 let extract_header dirname basename prog =
@@ -41,7 +41,7 @@ let extract_header dirname basename prog =
 
 let check_obsolete lusic basename =
   if lusic.obsolete then
-    raise (Error.Error (Location.dummy_loc, Error.Wrong_number basename))
+    raise (Error.Error (Location.dummy, Error.Wrong_number basename))
 
 (* encode and write a header in a file *)
 let write_lusic lusi (header : top_decl list) basename extension =
diff --git a/src/lusic.mli b/src/lusic.mli
new file mode 100644
index 00000000..e2068d98
--- /dev/null
+++ b/src/lusic.mli
@@ -0,0 +1,14 @@
+open Lustre_types
+
+type t = { obsolete : bool; from_lusi : bool; contents : program_t }
+
+(* extracts a header from a program representing module owner = dirname/basename *)
+val extract_header: string -> string -> program_t -> top_decl list
+
+(* read and decode a header from a file *)
+val read_lusic: string -> string -> t
+
+(* encode and write a header in a file *)
+val write_lusic: bool -> program_t -> string -> string -> unit
+
+val check_obsolete: t -> string -> unit
diff --git a/src/lustre_live.ml b/src/lustre_live.ml
index 6e66609a..913ab994 100644
--- a/src/lustre_live.ml
+++ b/src/lustre_live.ml
@@ -85,7 +85,7 @@ let set_live_of nid outputs locals sorted_eqs =
       Format.(
         fprintf fmt "Live variables of %s: %a@;@;" nid
           (pp_print_list ~pp_open_box:pp_open_vbox0 (fun fmt (i, l) ->
-               fprintf fmt "%i: %a" i pp_iset l))
+               fprintf fmt "%i: %a" i ISet.pp l))
           (Live.bindings l)));
   Hashtbl.add live nid l
 
diff --git a/src/lustre_live.mli b/src/lustre_live.mli
new file mode 100644
index 00000000..ae457e82
--- /dev/null
+++ b/src/lustre_live.mli
@@ -0,0 +1,6 @@
+open Utils
+open Lustre_types
+
+val inter_live_i_with: ident -> int -> var_decl list -> var_decl list
+val set_live_of: ident -> var_decl list -> var_decl list -> eq list -> unit
+val existential_vars: ident -> int -> eq -> var_decl list -> var_decl list
diff --git a/src/lustre_types.ml b/src/lustre_types.ml
index 19538aaf..824193cc 100644
--- a/src/lustre_types.ml
+++ b/src/lustre_types.ml
@@ -9,13 +9,9 @@
 (*                                                                  *)
 (********************************************************************)
 
-type ident = Utils.ident
+open Utils
 
-type rat = Utils.rat
-
-type tag = Utils.tag
-
-type label = Utils.ident
+type label = ident
 
 type type_dec = { ty_dec_desc : type_dec_desc; ty_dec_loc : Location.t }
 
@@ -29,7 +25,7 @@ and type_dec_desc =
   | Tydec_const of ident
   | Tydec_enum of ident list
   | Tydec_struct of (ident * type_dec_desc) list
-  | Tydec_array of Dimension.dim_expr * type_dec_desc
+  | Tydec_array of Dimension.t * type_dec_desc
 
 type typedec_desc = { tydec_id : ident }
 
@@ -60,8 +56,8 @@ type var_decl = {
   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;
+  mutable var_type : Types.t;
+  mutable var_clock : Clocks.t;
   var_loc : Location.t;
 }
 (* The tag of an expression is a unique identifier used to distinguish different
@@ -75,9 +71,9 @@ type var_decl = {
 and expr = {
   expr_tag : tag;
   expr_desc : expr_desc;
-  mutable expr_type : Types.type_expr;
-  mutable expr_clock : Clocks.clock_expr;
-  mutable expr_delay : Delay.delay_expr;
+  mutable expr_type : Types.t;
+  mutable expr_clock : Clocks.t;
+  mutable expr_delay : Delay.t;
   mutable expr_annot : expr_annot option;
   expr_loc : Location.t;
 }
@@ -90,8 +86,8 @@ and expr_desc =
   | 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_access of expr * Dimension.t
+  | Expr_power of expr * Dimension.t
   | Expr_pre of expr
   | Expr_when of expr * ident * label
   | Expr_merge of ident * (label * expr) list
@@ -109,8 +105,8 @@ and eexpr = {
   eexpr_qfexpr : expr;
   eexpr_quantifiers : (quantifier_type * var_decl list) list;
   eexpr_name : string option;
-  mutable eexpr_type : Types.type_expr;
-  mutable eexpr_clock : Clocks.clock_expr;
+  mutable eexpr_type : Types.t;
+  mutable eexpr_clock : Clocks.t;
   (* mutable eexpr_normalized: (var_decl * eq list * var_decl list) option; *)
   eexpr_loc : Location.t;
 }
@@ -131,7 +127,7 @@ type contract_import = {
   import_loc : Location.t;
 }
 
-type offset = Index of Dimension.dim_expr | Field of label
+type offset = Index of Dimension.t | Field of label
 
 type assert_t = { assert_expr : expr; assert_loc : Location.t }
 
@@ -169,13 +165,13 @@ type node_spec_t = Contract of contract_desc | NodeSpec of ident
 
 type node_desc = {
   node_id : ident;
-  mutable node_type : Types.type_expr;
-  mutable node_clock : Clocks.clock_expr;
+  mutable node_type : Types.t;
+  mutable node_clock : Clocks.t;
   node_inputs : var_decl list;
   node_outputs : var_decl list;
   node_locals : var_decl list;
   mutable node_gencalls : expr list;
-  mutable node_checks : Dimension.dim_expr list;
+  mutable node_checks : Dimension.t list;
   node_asserts : assert_t list;
   node_stmts : statement list;
   mutable node_dec_stateless : bool;
@@ -187,8 +183,8 @@ type node_desc = {
 
 type imported_node_desc = {
   nodei_id : ident;
-  mutable nodei_type : Types.type_expr;
-  mutable nodei_clock : Clocks.clock_expr;
+  mutable nodei_type : Types.t;
+  mutable nodei_clock : Clocks.t;
   nodei_inputs : var_decl list;
   nodei_outputs : var_decl list;
   nodei_stateless : bool;
@@ -202,7 +198,7 @@ type const_desc = {
   const_id : ident;
   const_loc : Location.t;
   const_value : constant;
-  mutable const_type : Types.type_expr;
+  mutable const_type : Types.t;
 }
 
 type top_decl_desc =
diff --git a/src/lustre_types.mli b/src/lustre_types.mli
new file mode 100644
index 00000000..438158e6
--- /dev/null
+++ b/src/lustre_types.mli
@@ -0,0 +1,229 @@
+open Utils
+
+type label = ident
+
+type type_dec = { ty_dec_desc : type_dec_desc; ty_dec_loc : Location.t }
+
+and type_dec_desc =
+  | Tydec_any
+  | Tydec_int
+  | Tydec_real
+  (* | Tydec_float *)
+  | Tydec_bool
+  | Tydec_clock of type_dec_desc
+  | Tydec_const of ident
+  | Tydec_enum of ident list
+  | Tydec_struct of (ident * type_dec_desc) list
+  | Tydec_array of Dimension.t * type_dec_desc
+
+type typedec_desc = { tydec_id : ident }
+
+type typedef_desc = { tydef_id : ident; tydef_desc : type_dec_desc }
+
+type clock_dec = { ck_dec_desc : clock_dec_desc; ck_dec_loc : Location.t }
+
+and clock_dec_desc = Ckdec_any | Ckdec_bool of (ident * ident) list
+
+type constant =
+  | Const_int of int
+  | Const_real of Real.t
+  | Const_array of constant list
+  | Const_tag of label
+  | Const_string of string
+  (* used only for annotations *)
+  | Const_modeid of string
+  (* used only for annotations *)
+  | Const_struct of (label * constant) list
+
+type quantifier_type = Exists | Forall
+
+type var_decl = {
+  var_id : ident;
+  var_orig : bool;
+  var_dec_type : type_dec;
+  var_dec_clock : clock_dec;
+  var_dec_const : bool;
+  var_dec_value : expr option;
+  mutable var_parent_nodeid : ident option;
+  mutable var_type : Types.t;
+  mutable var_clock : Clocks.t;
+  var_loc : Location.t;
+}
+(* The tag of an expression is a unique identifier used to distinguish different
+   instances of the same node *)
+
+(** The core language and its ast. Every element of the ast contains its
+    location in the program text. The type and clock of an ast element is
+    mutable (and initialized to dummy values). This avoids to have to duplicate
+    ast structures (e.g. ast, typed_ast, clocked_ast). *)
+
+and expr = {
+  expr_tag : tag;
+  expr_desc : expr_desc;
+  mutable expr_type : Types.t;
+  mutable expr_clock : Clocks.t;
+  mutable expr_delay : Delay.t;
+  mutable expr_annot : expr_annot option;
+  expr_loc : Location.t;
+}
+
+and expr_desc =
+  | Expr_const of constant
+  | Expr_ident of ident
+  | Expr_tuple of expr list
+  | 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.t
+  | Expr_power of expr * Dimension.t
+  | Expr_pre of expr
+  | Expr_when of expr * ident * label
+  | Expr_merge of ident * (label * expr) list
+  | Expr_appl of call_t
+
+and call_t = ident * expr * expr option
+(* The third part denotes the boolean condition for resetting *)
+
+and eq = { eq_lhs : ident list; eq_rhs : expr; eq_loc : Location.t }
+
+(* The tag of an expression is a unique identifier used to distinguish different
+   instances of the same node *)
+and eexpr = {
+  eexpr_tag : tag;
+  eexpr_qfexpr : expr;
+  eexpr_quantifiers : (quantifier_type * var_decl list) list;
+  eexpr_name : string option;
+  mutable eexpr_type : Types.t;
+  mutable eexpr_clock : Clocks.t;
+  (* mutable eexpr_normalized: (var_decl * eq list * var_decl list) option; *)
+  eexpr_loc : Location.t;
+}
+
+and expr_annot = { annots : (string list * eexpr) list; annot_loc : Location.t }
+
+type contract_mode = {
+  mode_id : ident;
+  require : eexpr list;
+  ensure : eexpr list;
+  mode_loc : Location.t;
+}
+
+type contract_import = {
+  import_nodeid : ident;
+  inputs : expr;
+  outputs : expr;
+  import_loc : Location.t;
+}
+
+type offset = Index of Dimension.t | Field of label
+
+type assert_t = { assert_expr : expr; assert_loc : Location.t }
+
+type statement = Eq of eq | Aut of automata_desc
+
+and automata_desc = {
+  aut_id : ident;
+  aut_handlers : handler_desc list;
+  aut_loc : Location.t;
+}
+
+and handler_desc = {
+  hand_state : ident;
+  hand_unless : (Location.t * expr * bool * ident) list;
+  hand_until : (Location.t * expr * bool * ident) list;
+  hand_locals : var_decl list;
+  hand_stmts : statement list;
+  hand_asserts : assert_t list;
+  hand_annots : expr_annot list;
+  hand_loc : Location.t;
+}
+
+type contract_desc = {
+  consts : var_decl list;
+  locals : var_decl list;
+  stmts : statement list;
+  assume : eexpr list;
+  guarantees : eexpr list;
+  modes : contract_mode list;
+  imports : contract_import list;
+  spec_loc : Location.t;
+}
+
+type node_spec_t = Contract of contract_desc | NodeSpec of ident
+
+type node_desc = {
+  node_id : ident;
+  mutable node_type : Types.t;
+  mutable node_clock : Clocks.t;
+  node_inputs : var_decl list;
+  node_outputs : var_decl list;
+  node_locals : var_decl list;
+  mutable node_gencalls : expr list;
+  mutable node_checks : Dimension.t list;
+  node_asserts : assert_t list;
+  node_stmts : statement list;
+  mutable node_dec_stateless : bool;
+  mutable node_stateless : bool option;
+  node_spec : node_spec_t option;
+  node_annot : expr_annot list;
+  node_iscontract : bool;
+}
+
+type imported_node_desc = {
+  nodei_id : ident;
+  mutable nodei_type : Types.t;
+  mutable nodei_clock : Clocks.t;
+  nodei_inputs : var_decl list;
+  nodei_outputs : var_decl list;
+  nodei_stateless : bool;
+  nodei_spec : node_spec_t option;
+  (* nodei_annot: expr_annot list; *)
+  nodei_prototype : string option;
+  nodei_in_lib : string list;
+}
+
+type const_desc = {
+  const_id : ident;
+  const_loc : Location.t;
+  const_value : constant;
+  mutable const_type : Types.t;
+}
+
+type top_decl_desc =
+  | Node of node_desc
+  | Const of const_desc
+  | ImportedNode of imported_node_desc
+  | Open of bool * string
+  (* the boolean set to true denotes a local lusi vs a lusi installed at system
+     level *)
+  | Include of string
+  (* the boolean set to true denotes a local lus vs a lus installed at system
+     level *)
+  | TypeDef of typedef_desc
+
+type top_decl = {
+  top_decl_desc : top_decl_desc;
+  (* description of the symbol *)
+  top_decl_owner : Location.filename;
+  (* the module where it is defined *)
+  top_decl_itf : bool;
+  (* header or source file ? *)
+  top_decl_loc : Location.t;
+}
+
+type program_t = top_decl list
+
+type dep_t = {
+  local : bool;
+  name : ident;
+  content : program_t;
+  is_stateful : bool;
+}
+
+type spec_types =
+  | LocalContract of contract_desc
+  | TopContract of top_decl list
+
+val tag_true: label
+val tag_false: label
diff --git a/src/lustre_utils.ml b/src/lustre_utils.ml
index 92b19db8..932c5ecb 100644
--- a/src/lustre_utils.ml
+++ b/src/lustre_utils.ml
@@ -9,7 +9,7 @@ let check_eq nd1 nd2 =
   (* TODO: check that nd1 and nd2 have the same signature *)
   let check_nd = Corelang.copy_node nd1 in
   (* to keep the type info *)
-  let loc = Location.dummy_loc in
+  let loc = Location.dummy in
   let ok_var =
     Corelang.mkvar_decl loc ~orig:false
       ( "__OK",
diff --git a/src/lustre_utils.mli b/src/lustre_utils.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/machine_code.ml b/src/machine_code.ml
index d550720e..1400cbe8 100644
--- a/src/machine_code.ml
+++ b/src/machine_code.ml
@@ -92,7 +92,7 @@ let specialize_to_c expr =
     expr
 
 let specialize_op expr =
-  match !Options.output with "C" -> specialize_to_c expr | _ -> expr
+  match !Options.output with Options.OutC -> specialize_to_c expr | _ -> expr
 
 let rec translate_expr env expr =
   let expr = specialize_op expr in
@@ -120,7 +120,7 @@ let rec translate_expr env expr =
          removed for C or Java backends. *)
       Fun ("ite", [ translate_expr g; translate_expr t; translate_expr e ])
     | _ ->
-      Format.eprintf "Normalization error for backend %s: %a@." !Options.output
+      Format.eprintf "Normalization error for backend %t: %a@." Options.pp_output
         Printers.pp_expr expr;
       raise NormalizationError
   in
@@ -138,7 +138,7 @@ let rec translate_act env (y, expr) =
   let translate_act = translate_act env in
   let translate_guard = translate_guard env in
   let translate_expr = translate_expr env in
-  let lustre_eq = Corelang.mkeq Location.dummy_loc ([ y.var_id ], expr) in
+  let lustre_eq = Corelang.mkeq Location.dummy ([ y.var_id ], expr) in
   match expr.expr_desc with
   | Expr_ite (c, t, e) ->
     let c = translate_guard c in
@@ -178,7 +178,7 @@ type machine_ctx = {
   (* Reset instructions *)
   si : instr_t list;
   (* Instances *)
-  j : (Lustre_types.top_decl * Dimension.dim_expr list) IMap.t;
+  j : (Lustre_types.top_decl * Dimension.t list) IMap.t;
   (* Step instructions *)
   s : instr_t list;
   (* Memory pack spec *)
diff --git a/src/machine_code_common.ml b/src/machine_code_common.ml
index d8361c02..a904c679 100644
--- a/src/machine_code_common.ml
+++ b/src/machine_code_common.ml
@@ -2,7 +2,8 @@ open Lustre_types
 open Machine_code_types
 open Spec_types
 open Corelang
-open Utils.Format
+open Utils
+open Format
 
 let print_statelocaltag = true
 
@@ -130,10 +131,12 @@ module PrintSpec = struct
 end
 
 let pp_spec m =
-  if !Options.spec <> "no" then
+  match !Options.spec with
+  | Options.SpecNo ->
+    pp_print_nothing
+  | _ ->
     pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_prologue:pp_print_cut
       (fun fmt -> fprintf fmt "@[<h>--%@ %a@]" (PrintSpec.pp_spec m))
-  else pp_print_nothing
 
 let rec pp_instr m fmt i =
   let pp_val = pp_val m in
@@ -217,7 +220,7 @@ let pp_step m fmt s =
 
 let pp_static_call fmt (node, args) =
   fprintf fmt "%s<%a>" (node_name node)
-    (pp_comma_list Dimension.pp_dimension)
+    (pp_comma_list Dimension.pp)
     args
 
 let pp_instance fmt (o1, o2) = fprintf fmt "(%s, %a)" o1 pp_static_call o2
@@ -229,9 +232,11 @@ let pp_memory_pack m fmt mp =
     mp.mpindex (PrintSpec.pp_spec m) mp.mpformula
 
 let pp_memory_packs m fmt =
-  if !Options.spec <> "no" then
+  match !Options.spec with
+  | Options.SpecNo ->
+    pp_print_nothing fmt
+  | _ ->
     fprintf fmt "@[<v 2>memory_packs:@ %a@]" (pp_print_list (pp_memory_pack m))
-  else pp_print_nothing fmt
 
 let pp_transition m fmt t =
   fprintf fmt "@[<v 2>Transition_%a<SELF>%a%a =@ %a@]" pp_print_string
@@ -242,9 +247,11 @@ let pp_transition m fmt t =
     t.tvars (PrintSpec.pp_spec m) t.tformula
 
 let pp_transitions m fmt =
-  if !Options.spec <> "no" then
+  match !Options.spec with
+  | Options.SpecNo ->
+    pp_print_nothing fmt
+  | _ ->
     fprintf fmt "@[<v 2>transitions:@ %a@]" (pp_print_list (pp_transition m))
-  else pp_print_nothing fmt
 
 let pp_machine fmt m =
   fprintf fmt
@@ -444,11 +451,10 @@ let get_machine_opt machines name =
     None machines
 
 let get_machine machines node_name =
-  try Utils.desome (get_machine_opt machines node_name)
-  with Utils.DeSome ->
+  try desome (get_machine_opt machines node_name)
+  with DeSome ->
     eprintf "Unable to find machine %s in machines %a@.@?" node_name
-      (Utils.fprintf_list ~sep:", " (fun fmt m ->
-           pp_print_string fmt m.mname.node_id))
+      (pp_comma_list (fun fmt m -> pp_print_string fmt m.mname.node_id))
       machines;
     assert false
 
@@ -526,15 +532,15 @@ let rec value_of_dimension m dim =
 let rec dimension_of_value value =
   match value.value_desc with
   | Cst (Const_tag t) when t = tag_true ->
-    Dimension.mkdim_bool Location.dummy_loc true
+    Dimension.mkdim_bool Location.dummy true
   | Cst (Const_tag t) when t = tag_false ->
-    Dimension.mkdim_bool Location.dummy_loc false
+    Dimension.mkdim_bool Location.dummy false
   | Cst (Const_int i) ->
-    Dimension.mkdim_int Location.dummy_loc i
+    Dimension.mkdim_int Location.dummy i
   | Var v ->
-    Dimension.mkdim_ident Location.dummy_loc v.var_id
+    Dimension.mkdim_ident Location.dummy v.var_id
   | Fun (f, args) ->
-    Dimension.mkdim_appl Location.dummy_loc f (List.map dimension_of_value args)
+    Dimension.mkdim_appl Location.dummy f (List.map dimension_of_value args)
   | _ ->
     assert false
 
diff --git a/src/machine_code_common.mli b/src/machine_code_common.mli
index 254ccd55..ae2ba454 100644
--- a/src/machine_code_common.mli
+++ b/src/machine_code_common.mli
@@ -1,116 +1,120 @@
+open Utils
+open Lustre_types
+open Machine_code_types
+
 val pp_val :
-  Machine_code_types.machine_t ->
+  machine_t ->
   Format.formatter ->
-  Machine_code_types.value_t ->
+  value_t ->
   unit
 
-val is_memory : Machine_code_types.machine_t -> Lustre_types.var_decl -> bool
+val is_memory : machine_t -> var_decl -> bool
 
-val is_reset_flag : Lustre_types.var_decl -> bool
+val is_reset_flag : var_decl -> bool
 
-val is_output : Machine_code_types.machine_t -> Lustre_types.var_decl -> bool
+val is_output : machine_t -> var_decl -> bool
 
-val is_const_value : Machine_code_types.value_t -> bool
+val is_const_value : value_t -> bool
 
 val get_const_assign :
-  Machine_code_types.machine_t ->
-  Lustre_types.var_decl ->
-  Machine_code_types.value_t
+  machine_t ->
+  var_decl ->
+  value_t
 
-val get_stateless_status_node : Lustre_types.node_desc -> bool * bool
+val get_stateless_status_node : node_desc -> bool * bool
 
-val get_stateless_status : Machine_code_types.machine_t -> bool * bool
+val get_stateless_status : machine_t -> bool * bool
 
-val get_stateless_status_top_decl : Lustre_types.top_decl -> bool * bool
+val get_stateless_status_top_decl : top_decl -> bool * bool
 
-val is_stateless : Machine_code_types.machine_t -> bool
+val is_stateless : machine_t -> bool
 
 val mk_val :
-  Machine_code_types.value_t_desc ->
-  Types.type_expr ->
-  Machine_code_types.value_t
+  value_t_desc ->
+  Types.t ->
+  value_t
 
-val vdecl_to_val : Lustre_types.var_decl -> Machine_code_types.value_t
+val vdecl_to_val : var_decl -> value_t
 
 val vdecls_to_vals :
-  Lustre_types.var_decl list -> Machine_code_types.value_t list
+  var_decl list -> value_t list
 
-val id_to_tag : Lustre_types.ident -> Machine_code_types.value_t
+val id_to_tag : ident -> value_t
 
 val mk_conditional :
-  ?lustre_eq:Lustre_types.eq ->
-  Machine_code_types.value_t ->
-  Machine_code_types.instr_t list ->
-  Machine_code_types.instr_t list ->
-  Machine_code_types.instr_t
+  ?lustre_eq:eq ->
+  value_t ->
+  instr_t list ->
+  instr_t list ->
+  instr_t
 
 val mk_branch :
-  ?lustre_eq:Lustre_types.eq ->
-  Machine_code_types.value_t ->
-  (Lustre_types.label * Machine_code_types.instr_t list) list ->
-  Machine_code_types.instr_t
+  ?lustre_eq:eq ->
+  value_t ->
+  (label * instr_t list) list ->
+  instr_t
 
 val mk_branch' :
-  ?lustre_eq:Lustre_types.eq ->
-  Lustre_types.var_decl ->
-  (Lustre_types.label * Machine_code_types.instr_t list) list ->
-  Machine_code_types.instr_t
+  ?lustre_eq:eq ->
+  var_decl ->
+  (label * instr_t list) list ->
+  instr_t
 
 val mk_assign :
-  ?lustre_eq:Lustre_types.eq ->
-  Lustre_types.var_decl ->
-  Machine_code_types.value_t ->
-  Machine_code_types.instr_t
+  ?lustre_eq:eq ->
+  var_decl ->
+  value_t ->
+  instr_t
 
-val empty_machine : Machine_code_types.machine_t
+val empty_machine : machine_t
 
-val arrow_machine : Machine_code_types.machine_t
+val arrow_machine : machine_t
 
 val new_instance :
-  Lustre_types.top_decl -> Lustre_types.tag -> Lustre_types.ident
+  top_decl -> tag -> ident
 
 val value_of_dimension :
-  Machine_code_types.machine_t ->
-  Dimension.dim_expr ->
-  Machine_code_types.value_t
+  machine_t ->
+  Dimension.t ->
+  value_t
 
-val dimension_of_value : Machine_code_types.value_t -> Dimension.dim_expr
+val dimension_of_value : value_t -> Dimension.t
 
 val pp_instr :
-  Machine_code_types.machine_t ->
+  machine_t ->
   Format.formatter ->
-  Machine_code_types.instr_t ->
+  instr_t ->
   unit
 
 val pp_instrs :
-  Machine_code_types.machine_t ->
+  machine_t ->
   Format.formatter ->
-  Machine_code_types.instr_t list ->
+  instr_t list ->
   unit
 
-val pp_machines : Format.formatter -> Machine_code_types.machine_t list -> unit
+val pp_machines : Format.formatter -> machine_t list -> unit
 
 val get_machine_opt :
-  Machine_code_types.machine_t list ->
+  machine_t list ->
   string ->
-  Machine_code_types.machine_t option
+  machine_t option
 
 (* Same function but fails if no such a machine exists *)
 val get_machine :
-  Machine_code_types.machine_t list -> string -> Machine_code_types.machine_t
+  machine_t list -> string -> machine_t
 
 val get_node_def :
-  string -> Machine_code_types.machine_t -> Lustre_types.node_desc
+  string -> machine_t -> node_desc
 
 val join_guards_list :
-  Machine_code_types.instr_t list -> Machine_code_types.instr_t list
+  instr_t list -> instr_t list
 
-val machine_vars : Machine_code_types.machine_t -> Lustre_types.var_decl list
+val machine_vars : machine_t -> var_decl list
 
 module PrintSpec : sig
   val pp_spec :
-    Machine_code_types.machine_t ->
+    machine_t ->
     Format.formatter ->
-    Machine_code_types.value_t Spec_types.formula_t ->
+    value_t Spec_types.formula_t ->
     unit
 end
diff --git a/src/machine_code_types.ml b/src/machine_code_types.mli
similarity index 95%
rename from src/machine_code_types.ml
rename to src/machine_code_types.mli
index 7bd08add..7f2ecfaa 100644
--- a/src/machine_code_types.ml
+++ b/src/machine_code_types.mli
@@ -1,10 +1,11 @@
 (************ Machine code types *************)
+open Utils
 open Lustre_types
 open Spec_types
 
 type value_t = {
   value_desc : value_t_desc;
-  value_type : Types.type_expr;
+  value_type : Types.t;
   value_annot : expr_annot option;
 }
 
@@ -50,7 +51,7 @@ type step_t = {
   step_asserts : value_t list;
 }
 
-type static_call = top_decl * Dimension.dim_expr list
+type static_call = top_decl * Dimension.t list
 
 type mc_transition_t = value_t transition_t
 
diff --git a/src/main_lustre_compiler.mli b/src/main_lustre_compiler.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/main_lustre_testgen.mli b/src/main_lustre_testgen.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/main_lustre_verifier.mli b/src/main_lustre_verifier.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/mmap.mli b/src/mmap.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/modules.ml b/src/modules.ml
index 084cdf2a..8ef27827 100644
--- a/src/modules.ml
+++ b/src/modules.ml
@@ -340,5 +340,5 @@ let load ~is_header program =
     (* Format.eprintf "Import error: %a%a@."
      *   Error.pp_error_msg err
      *   Location.pp_loc loc; *)
-    Format.eprintf "Import error: %a@." Error.pp_error_msg err;
+    Format.eprintf "Import error: %a@." Error.pp err;
     raise exc
diff --git a/src/modules.mli b/src/modules.mli
index 4aa08751..cb792261 100644
--- a/src/modules.mli
+++ b/src/modules.mli
@@ -14,8 +14,8 @@ open Lustre_types
 val load :
   is_header:bool ->
   program_t ->
-  program_t * dep_t list * (Typing.type_expr Env.t * Clocks.clock_expr Env.t)
+  program_t * dep_t list * (Types.t Env.t * Clocks.t Env.t)
 
 (* Returns an updated env with the type/clock declaration of the program *)
 val get_envs_from_top_decls :
-  program_t -> Typing.type_expr Env.t * Clocks.clock_expr Env.t
+  program_t -> Types.t Env.t * Clocks.t Env.t
diff --git a/src/mutation.mli b/src/mutation.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/normalization.ml b/src/normalization.ml
index c9fe1d47..6b5a86b7 100644
--- a/src/normalization.ml
+++ b/src/normalization.ml
@@ -86,7 +86,7 @@ let expr_once loc ck =
   }
 
 let is_expr_once =
-  let dummy_expr_once = expr_once Location.dummy_loc (Clocks.new_var true) in
+  let dummy_expr_once = expr_once Location.dummy (Clocks.new_var true) in
   fun expr -> Corelang.is_eq_expr expr dummy_expr_once
 
 let unfold_arrow expr =
@@ -103,7 +103,7 @@ let get_expr_alias defs expr =
     Some
       (List.find
          (fun eq ->
-           Clocks.eq_clock expr.expr_clock eq.eq_rhs.expr_clock
+           Clocks.equal expr.expr_clock eq.eq_rhs.expr_clock
            && is_eq_expr eq.eq_rhs expr)
          defs)
   with Not_found -> None
@@ -151,7 +151,7 @@ let mk_expr_alias_opt opt norm_ctx (defs, vars) expr =
   if !debug then
     Log.report ~plugin:"normalization" ~level:2 (fun fmt ->
         Format.fprintf fmt "mk_expr_alias_opt %B %a %a %a@." opt
-          Printers.pp_expr expr Types.print_ty expr.expr_type Clocks.print_ck
+          Printers.pp_expr expr Types.print_ty expr.expr_type Clocks.pp
           expr.expr_clock);
   match expr.expr_desc with
   | Expr_ident _ -> (defs, vars), expr
@@ -579,8 +579,8 @@ let normalize_pred_eexpr norm_ctx (def, vars) ee =
     with Types.Error (loc, err) as exc ->
       eprintf "Typing error for eexpr %a: %a%a%a@." Printers.pp_eexpr ee
         Types.pp_error err
-        (Utils.fprintf_list ~sep:", " Printers.pp_node_eq)
-        defs Location.pp_loc loc;
+        (pp_comma_list Printers.pp_node_eq)
+        defs Location.pp loc;
 
       raise exc
 
@@ -834,7 +834,7 @@ let normalize_node node =
                   [ "traceability" ];
                 [ "traceability" ], pair)
               diff_vars;
-          annot_loc = Location.dummy_loc;
+          annot_loc = Location.dummy;
         }
       in
       norm_traceability :: node.node_annot
diff --git a/src/normalization.mli b/src/normalization.mli
index 51027651..80503773 100644
--- a/src/normalization.mli
+++ b/src/normalization.mli
@@ -1,3 +1,4 @@
+open Utils
 open Lustre_types
 
 type param_t = {
diff --git a/src/optimize_machine.ml b/src/optimize_machine.ml
index 2f9d14ac..2e25139d 100644
--- a/src/optimize_machine.ml
+++ b/src/optimize_machine.ml
@@ -20,7 +20,7 @@ open Dimension
 module Mpfr = Lustrec_mpfr
 
 let pp_elim m fmt elim =
-  pp_imap ~comment:"/* elim table: */" (pp_val m) fmt elim
+  IMap.pp ~comment:"/* elim table: */" (pp_val m) fmt elim
 (* Format.fprintf fmt "@[<hv 0>@[<hv 2>{ /* elim table: */";
  * IMap.iter (fun v expr -> Format.fprintf fmt "@ %s |-> %a," v (pp_val m) expr) elim;
  * Format.fprintf fmt "@]@ }@]" *)
@@ -96,10 +96,10 @@ let rec simplify_cst_expr m offset typ cst =
   match offset, cst with
   | [], _ ->
     mk_val (Cst cst) typ
-  | Index i :: q, Const_array cl when Dimension.is_dimension_const i ->
+  | Index i :: q, Const_array cl when Dimension.is_const i ->
     let elt_typ = Types.array_element_type typ in
     simplify_cst_expr m q elt_typ
-      (List.nth cl (Dimension.size_const_dimension i))
+      (List.nth cl (Dimension.size_const i))
   | Index i :: q, Const_array cl ->
     let elt_typ = Types.array_element_type typ in
     unfold_expr_offset m [ Index i ]
@@ -131,8 +131,8 @@ let simplify_expr_offset m expr =
       expr
     | Index _ :: q, Power (expr, _) ->
       simplify q expr
-    | Index i :: q, Array vl when Dimension.is_dimension_const i ->
-      simplify q (List.nth vl (Dimension.size_const_dimension i))
+    | Index i :: q, Array vl when Dimension.is_const i ->
+      simplify q (List.nth vl (Dimension.size_const i))
     | Index i :: q, Array vl ->
       unfold_expr_offset m [ Index i ]
         (mk_val (Array (List.map (simplify q) vl)) expr.value_type)
@@ -182,8 +182,8 @@ let is_unfoldable_expr fanin expr =
       unfold_const q (List.assoc f fl)
     | [], Const_struct _ ->
       false
-    | Index i :: q, Const_array cl when Dimension.is_dimension_const i ->
-      unfold_const q (List.nth cl (Dimension.size_const_dimension i))
+    | Index i :: q, Const_array cl when Dimension.is_const i ->
+      unfold_const q (List.nth cl (Dimension.size_const i))
     | _, Const_array _ ->
       false
     | _ ->
@@ -199,8 +199,8 @@ let is_unfoldable_expr fanin expr =
       false
     | Index _ :: q, Power (v, _) ->
       unfold q v
-    | Index i :: q, Array vl when Dimension.is_dimension_const i ->
-      unfold q (List.nth vl (Dimension.size_const_dimension i))
+    | Index i :: q, Array vl when Dimension.is_const i ->
+      unfold q (List.nth vl (Dimension.size_const i))
     | _, Array _ ->
       false
     | _, Access (v, i) ->
@@ -298,7 +298,7 @@ and instr_unfold m fanin instrs (elim : (value_t * eq) IMap.t) instr =
 let static_call_unfold elim (inst, (n, args)) =
   let replace v =
     try dimension_of_value (IMap.find v elim)
-    with Not_found -> Dimension.mkdim_ident Location.dummy_loc v
+    with Not_found -> Dimension.mkdim_ident Location.dummy v
   in
   inst, (n, List.map (Dimension.expr_replace_expr replace) args)
 
@@ -351,7 +351,7 @@ let instr_of_const top_const =
   let vdecl =
     mkvar_decl loc
       ( id,
-        mktyp Location.dummy_loc Tydec_any,
+        mktyp Location.dummy Tydec_any,
         mkclock loc Ckdec_any,
         true,
         None,
@@ -880,7 +880,7 @@ let optimize params prog node_schs machine_code =
   (* Optimize machine code *)
   let prog, machine_code, removed_table =
     if
-      !Options.optimization >= 2 && !Options.output <> "emf"
+      !Options.optimization >= 2 && !Options.output <> Options.OutEMF
       (*&& !Options.output <> "horn"*)
     then (
       Log.report ~level:1 (fun fmt ->
@@ -892,7 +892,7 @@ let optimize params prog node_schs machine_code =
       in
       Log.report ~level:3 (fun fmt ->
           Format.fprintf fmt "@ Eliminated flows: %a@ "
-            (pp_imap (fun fmt m -> pp_elim empty_machine fmt (IMap.map fst m)))
+            (IMap.pp (fun fmt m -> pp_elim empty_machine fmt (IMap.map fst m)))
             removed_table);
       Log.report ~level:3 (fun fmt ->
           Format.fprintf fmt
diff --git a/src/optimize_machine.mli b/src/optimize_machine.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/optimize_prog.mli b/src/optimize_prog.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/options.ml b/src/options.ml
index 7a481a4d..e19289a8 100644
--- a/src/options.ml
+++ b/src/options.ml
@@ -9,10 +9,6 @@
 (*                                                                  *)
 (********************************************************************)
 
-let version = Version.number
-
-let codename = Version.codename
-
 let include_dirs = ref [ "." ]
 
 let main_node = ref ""
@@ -31,9 +27,29 @@ let ansi = ref false
 
 let check = ref false
 
-let spec = ref "no"
-
-let output = ref "C"
+type option_spec =
+  | SpecNo
+  | SpecACSL
+  | SpecC
+
+let spec = ref SpecNo
+
+type option_output =
+  | OutC
+  | OutAda
+  | OutEMF
+  | OutHorn
+  | OutLustre
+
+let output = ref OutC
+
+let pp_output fmt =
+  Format.pp_print_string fmt (match !output with
+  | OutC -> "C"
+  | OutAda -> "Ada"
+  | OutEMF -> "EMF"
+  | OutHorn -> "Horn"
+  | OutLustre -> "Lustre")
 
 let dest_dir = ref "."
 
diff --git a/src/options.mli b/src/options.mli
new file mode 100644
index 00000000..9a9d5206
--- /dev/null
+++ b/src/options.mli
@@ -0,0 +1,78 @@
+val kind2_print: bool ref
+val mpfr: bool ref
+val print_dec_types: bool ref
+val verbose_level: int ref
+val main_node: string ref
+val global_inline: bool ref
+val mpfr_prec: int ref
+
+type option_spec =
+  | SpecNo
+  | SpecACSL
+  | SpecC
+
+val spec: option_spec ref
+
+type option_output =
+  | OutC
+  | OutAda
+  | OutEMF
+  | OutHorn
+  | OutLustre
+  (* | OutACSL *)
+
+val output: option_output ref
+
+val pp_output: Format.formatter -> unit
+
+val ansi: bool ref
+
+val int_type: string ref
+val real_type: string ref
+
+val optimization: int ref
+
+val include_dirs: string list ref
+
+val dest_dir: string ref
+
+val print_types: bool ref
+val print_clocks: bool ref
+val print_nodes: bool ref
+val print_prec_double: int ref
+
+val solve_al: bool ref
+val al_nb_max: int ref
+
+val delay_calculus: bool ref
+
+val static_mem: bool ref
+
+val check: bool ref
+
+val lusi: bool ref
+
+val traces: bool ref
+
+val horn_cex: bool ref
+val horn_query: bool ref
+
+val sfunction: string ref
+
+val print_reuse: bool ref
+
+val const_unfold: bool ref
+
+val witnesses: bool ref
+
+val cpp: bool ref
+
+val integer_div_euclidean: bool ref
+
+val mauve: string ref
+
+val nb_mutants: int ref
+
+val gen_mcdc: bool ref
+
+val no_mutation_suffix: bool ref
diff --git a/src/options_management.ml b/src/options_management.ml
index fa950c51..fd9f1e5e 100644
--- a/src/options_management.ml
+++ b/src/options_management.ml
@@ -15,7 +15,7 @@ let print_version () =
   printf
     "@[<v>Lustrec compiler, version %s (%s)@,\
      Standard lib: %s@,\
-     User provided include directory: @[<h>%a@]@]@." version codename
+     User provided include directory: @[<h>%a@]@]@." Version.number Version.codename
     Version.include_path
     (pp_print_list ~pp_sep:pp_print_space pp_print_string)
     !include_dirs
@@ -50,7 +50,7 @@ let search_lib_path (local, full_file_name) =
   match name with
   | None ->
     Format.eprintf "Unable to find library %s in paths %a@.@?" full_file_name
-      (Utils.fprintf_list ~sep:", " Format.pp_print_string)
+      (Utils.Format.pp_comma_list Format.pp_print_string)
       paths;
     raise Not_found
   | Some s ->
@@ -130,40 +130,40 @@ let lustrec_options =
         "only generates a .lusi interface source file from a Lustre source \
          <default: no generation>" );
       ( "-no-spec",
-        Arg.Unit (fun () -> spec := "no"),
+        Arg.Unit (fun () -> spec := SpecNo),
         "do not generate any specification" );
       ( "-acsl-spec",
-        Arg.Unit (fun () -> spec := "acsl"),
+        Arg.Unit (fun () -> spec := SpecACSL),
         "generates an ACSL encoding of the specification. Only meaningful for \
          the C backend <default>" );
       ( "-c-spec",
-        Arg.Unit (fun () -> spec := "c"),
+        Arg.Unit (fun () -> spec := SpecC),
         "generates a C encoding of the specification instead of ACSL contracts \
          and annotations. Only meaningful for the C backend" );
       (* "-java", Arg.Unit (fun () -> output := "java"), "generates Java output
          instead of C"; *)
       ( "-ada",
-        Arg.Unit (fun () -> set_backend "Ada"),
+        Arg.Unit (fun () -> set_backend OutAda),
         "generates Ada encoding output instead of C" );
       ( "-horn",
-        Arg.Unit (fun () -> set_backend "horn"),
+        Arg.Unit (fun () -> set_backend OutHorn),
         "generates Horn clauses encoding output instead of C" );
       ( "-horn-traces",
         Arg.Unit
           (fun () ->
-            set_backend "horn";
+            set_backend OutHorn;
             traces := true),
         "produce traceability file for Horn backend. Enable the horn backend." );
       ( "-horn-cex",
         Arg.Unit
           (fun () ->
-            set_backend "horn";
+            set_backend OutHorn;
             horn_cex := true),
         "generate cex enumeration. Enable the horn backend (work in progress)" );
       ( "-horn-query",
         Arg.Unit
           (fun () ->
-            set_backend "horn";
+            set_backend OutHorn;
             horn_query := true),
         "generate queries in generated Horn file. Enable the horn backend \
          (work in progress)" );
@@ -172,10 +172,10 @@ let lustrec_options =
         "Gets the endpoint predicate of the \x1b[4msfunction\x1b[0m" );
       "-print-reuse", Arg.Set print_reuse, "prints variable reuse policy";
       ( "-lustre",
-        Arg.Unit (fun () -> output := "lustre"),
+        Arg.Unit (fun () -> set_backend OutLustre),
         "generates Lustre output, performing all active optimizations" );
       ( "-emf",
-        Arg.Unit (fun () -> set_backend "emf"),
+        Arg.Unit (fun () -> set_backend OutEMF),
         "generates EMF output, to be used by CocoSim" );
       ( "-inline",
         Arg.Unit
diff --git a/src/options_management.mli b/src/options_management.mli
new file mode 100644
index 00000000..9447f369
--- /dev/null
+++ b/src/options_management.mli
@@ -0,0 +1,6 @@
+val core_dependency: string -> string
+val plugin_opt: string * (unit -> unit) * (Format.formatter -> unit) *
+                (string * Arg.spec * string) list -> (string * Arg.spec * string) list
+
+val name_dependency: ('a * string) -> string -> string
+val get_witness_dir: string -> string
diff --git a/src/parsers/lexerLustreSpec.mll b/src/parsers/lexerLustreSpec.mll
index b725e36c..795e32fd 100644
--- a/src/parsers/lexerLustreSpec.mll
+++ b/src/parsers/lexerLustreSpec.mll
@@ -15,6 +15,8 @@
   open Parser_lustre
   open Utils
 
+  module Lex = MenhirLib.LexerUtil
+
   let str_buf = Buffer.create 1024
 
   type error =
@@ -38,7 +40,7 @@ let error lexbuf err =
   raise (Error (Location.curr lexbuf, err))
 
 let newline token lexbuf =
-  Location.Lex.newline lexbuf;
+  Lex.newline lexbuf;
   token lexbuf
 
 (* As advised by Caml documentation. This way a single lexer rule is
diff --git a/src/parsers/lexer_lustre.mll b/src/parsers/lexer_lustre.mll
index f31fe8ff..31c8c507 100644
--- a/src/parsers/lexer_lustre.mll
+++ b/src/parsers/lexer_lustre.mll
@@ -13,6 +13,8 @@
 open Parser_lustre
 open Utils
 
+module Lex = MenhirLib.LexerUtil
+
 (* As advised by Caml documentation. This way a single lexer rule is
    used to handle all the possible keywords. *)
 let keyword_table =
@@ -113,7 +115,7 @@ let error lexbuf =
   error_with (Location.curr lexbuf)
 
 let newline token lexbuf =
-  Location.Lex.newline lexbuf;
+  Lex.newline lexbuf;
   token lexbuf
 
 let make_annot orig_loc s =
diff --git a/src/parsers/parse.ml b/src/parsers/parse.ml
index faa1b25b..eadffe6e 100644
--- a/src/parsers/parse.ml
+++ b/src/parsers/parse.ml
@@ -96,7 +96,7 @@ let reparse (module Lexer : LEXER) ?orig_loc filename start src =
     (* Expand away the $i keywords that might appear in the message. *)
     (* let message = E.expand (get src checkpoint) message in *)
     (* Show these three components. *)
-    eprintf "@[<v>%aSyntax error %s.@,%s@]@." Location.pp_loc loc indication
+    eprintf "@[<v>%aSyntax error %s.@,%s@]@." Location.pp loc indication
       message;
     raise Error
   in
@@ -113,7 +113,7 @@ let parse (module Lexer : LEXER) ?orig_loc filename src lexbuf start_mono
     let loc =
       match orig_loc with Some loc' -> Location.shift loc' loc | _ -> loc
     in
-    eprintf "@[<v>%aSyntax error.@,%a@]@." Location.pp_loc loc Lexer.pp_error
+    eprintf "@[<v>%aSyntax error.@,%a@]@." Location.pp loc Lexer.pp_error
       err;
     raise Error
   | Parser_lustre.Error ->
diff --git a/src/parsers/parse.mli b/src/parsers/parse.mli
new file mode 100644
index 00000000..6d552617
--- /dev/null
+++ b/src/parsers/parse.mli
@@ -0,0 +1,20 @@
+type start_symbol = Header | Program
+
+module type LEXER = sig
+  val token : Lexing.lexbuf -> Parser_lustre.token
+
+  type error
+
+  exception Error of Location.t * error
+
+  val pp_error : Format.formatter -> error -> unit
+end
+
+module Inc: module type of Parser_lustre_table.Incremental
+
+val parse: (module LEXER) -> ?orig_loc:Location.t -> Location.filename -> string ->
+  Lexing.lexbuf ->
+  ((Lexing.lexbuf -> Parser_lustre.token) -> Lexing.lexbuf -> 'a) ->
+  (Lexing.position -> 'b Parser_lustre_table.MenhirInterpreter.checkpoint) -> 'a
+
+val parse_filename: (module LEXER) -> Location.filename -> start_symbol -> Lustre_types.program_t
diff --git a/src/pathConditions.mli b/src/pathConditions.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plugins/mpfr/lustrec_mpfr.mli b/src/plugins/mpfr/lustrec_mpfr.mli
new file mode 100644
index 00000000..60f43087
--- /dev/null
+++ b/src/plugins/mpfr/lustrec_mpfr.mli
@@ -0,0 +1 @@
+val unfoldable_value: Machine_code_types.value_t -> bool
diff --git a/src/plugins/pluginList.ml b/src/plugins/pluginList.ml
index ad10f547..06d8de15 100644
--- a/src/plugins/pluginList.ml
+++ b/src/plugins/pluginList.ml
@@ -1,3 +1,3 @@
-let registered : (module PluginType.S) list ref = ref []
+let registered = ref []
 
 let plugins () = !registered
diff --git a/src/plugins/pluginList.mli b/src/plugins/pluginList.mli
new file mode 100644
index 00000000..ed6f294e
--- /dev/null
+++ b/src/plugins/pluginList.mli
@@ -0,0 +1,2 @@
+val registered: (module PluginType.S) list ref
+val plugins: unit -> (module PluginType.S) list
diff --git a/src/plugins/pluginType.ml b/src/plugins/pluginType.ml
index 4de83163..a4bd750c 100644
--- a/src/plugins/pluginType.ml
+++ b/src/plugins/pluginType.ml
@@ -23,8 +23,14 @@ module type S = sig
 end
 
 module Default = struct
+  let name = "default"
+
+  let activate () = ()
+
   let usage fmt = Format.fprintf fmt "No specific help."
 
+  let options = []
+
   let init () = ()
 
   let check_force_stateful () = false
diff --git a/src/plugins/pluginType.mli b/src/plugins/pluginType.mli
new file mode 100644
index 00000000..53c395c5
--- /dev/null
+++ b/src/plugins/pluginType.mli
@@ -0,0 +1,25 @@
+module type S = sig
+  val name : string
+
+  val activate : unit -> unit
+
+  val usage : Format.formatter -> unit
+
+  val options : (string * Arg.spec * string) list
+
+  val init : unit -> unit
+
+  val check_force_stateful : unit -> bool
+
+  val refine_machine_code :
+    Lustre_types.top_decl list ->
+    Machine_code_types.machine_t list ->
+    Machine_code_types.machine_t list
+
+  val c_backend_main_loop_body_prefix :
+    string -> string -> Format.formatter -> unit -> unit
+
+  val c_backend_main_loop_body_suffix : Format.formatter -> unit -> unit
+end
+
+module Default: S
diff --git a/src/plugins/plugins.mli b/src/plugins/plugins.mli
new file mode 100644
index 00000000..093db4ae
--- /dev/null
+++ b/src/plugins/plugins.mli
@@ -0,0 +1,4 @@
+open Utils
+open Lustre_types
+
+val inline_annots: (ident -> ident) -> expr_annot list -> expr_annot list
diff --git a/src/plugins/salsa/machine_salsa_opt.mli b/src/plugins/salsa/machine_salsa_opt.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plugins/salsa/salsaDatatypes.mli b/src/plugins/salsa/salsaDatatypes.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plugins/salsa/salsa_plugin.mli b/src/plugins/salsa/salsa_plugin.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plugins/scopes/scopes.ml b/src/plugins/scopes/scopes.ml
index 9274265c..070aa37c 100644
--- a/src/plugins/scopes/scopes.ml
+++ b/src/plugins/scopes/scopes.ml
@@ -1,3 +1,4 @@
+open Utils
 open Lustre_types
 open Corelang
 open Machine_code_types
@@ -37,7 +38,7 @@ let rec compute_scopes ?(first = true) prog root_node : scope_t list =
                 (nodeid, vid) :: res
               with Not_found ->
                 Format.eprintf "eq=%a@.local_vars=%a@." Printers.pp_node_eq eq
-                  (Utils.fprintf_list ~sep:"," Printers.pp_var)
+                  (Format.pp_comma_list Printers.pp_var)
                   local_vars;
                 assert false)
             | Eq _ ->
@@ -58,10 +59,10 @@ let rec compute_scopes ?(first = true) prog root_node : scope_t list =
   with Not_found -> []
 
 let print_scopes =
-  Utils.fprintf_list ~sep:"@ " (fun fmt ((_, v) as s) ->
-      Format.fprintf fmt "%a: %a"
-        (Utils.fprintf_list ~sep:"." Format.pp_print_string)
-        (scope_to_sl s) Types.print_ty v.var_type)
+  Format.(pp_print_list (fun fmt ((_, v) as s) ->
+      fprintf fmt "%a: %a"
+        (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt ".") pp_print_string)
+        (scope_to_sl s) Types.print_ty v.var_type))
 
 (* let print_path fmt p = *)
 (* Utils.fprintf_list ~sep:"." (fun fmt (id, _) -> Format.pp_print_string fmt
@@ -206,7 +207,7 @@ let pp_scopes fmt scopes =
   List.iteri
     (fun idx (id, (var_path, var)) ->
       Format.fprintf fmt "@ %t;" (fun fmt ->
-          C_backend_common.print_put_var fmt
+          C_backend_common.pp_put_var fmt
             ("_scopes" ^ string_of_int (idx + 1))
             id (*var*) var.var_type var_path))
     scopes_vars
@@ -307,7 +308,7 @@ let option_all_scopes = ref false
 (* let option_mems_scopes = ref false 
  * let option_input_scopes = ref false *)
 
-let scopes_map : (Lustre_types.ident list * scope_t) list ref = ref []
+let scopes_map : (ident list * scope_t) list ref = ref []
 
 let process_scopes main_node prog machines =
   let all_scopes = compute_scopes prog !Options.main_node in
@@ -322,9 +323,9 @@ let process_scopes main_node prog machines =
       (fun sl ->
         let res = is_valid_path sl main_node prog machines in
         if not res then
-          Format.eprintf "Scope %a is cancelled due to variable removal@."
-            (Utils.fprintf_list ~sep:"." Format.pp_print_string)
-            sl;
+          Format.(eprintf "Scope %a is cancelled due to variable removal@."
+            (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt ".") pp_print_string)
+            sl);
         res)
       selected_scopes
   in
diff --git a/src/plugins/scopes/scopes.mli b/src/plugins/scopes/scopes.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/printers.ml b/src/printers.ml
index 09e4f8b3..9cb24356 100644
--- a/src/printers.ml
+++ b/src/printers.ml
@@ -50,13 +50,13 @@ and pp_var_type_dec_desc fmt tdesc =
   | Tydec_const t ->
     fprintf fmt "%s" t
   | Tydec_enum id_list ->
-    fprintf fmt "enum {%a }" (fprintf_list ~sep:", " pp_print_string) id_list
+    fprintf fmt "enum {%a }" (pp_comma_list pp_print_string) id_list
   | Tydec_struct f_list ->
     fprintf fmt "struct {%a }"
-      (fprintf_list ~sep:" " pp_var_struct_type_field)
+      (pp_print_list pp_var_struct_type_field)
       f_list
   | Tydec_array (s, t) ->
-    fprintf fmt "%a^%a" pp_var_type_dec_desc t Dimension.pp_dimension s
+    fprintf fmt "%a^%a" pp_var_type_dec_desc t Dimension.pp s
 
 let pp_var_type_dec fmt ty = pp_var_type_dec_desc fmt ty.ty_dec_desc
 
@@ -68,9 +68,9 @@ let pp_var_type fmt id =
   if !Options.print_dec_types then pp_var_type_dec fmt id.var_dec_type
   else Types.print_node_ty fmt id.var_type
 
-let pp_var_clock fmt id = Clocks.print_ck_suffix fmt id.var_clock
+let pp_var_clock fmt id = Clocks.pp_suffix fmt id.var_clock
 
-let pp_eq_lhs = fprintf_list ~sep:", " pp_print_string
+let pp_eq_lhs = pp_comma_list pp_print_string
 
 let pp_var fmt id =
   fprintf fmt "%s%s: %a"
@@ -78,7 +78,7 @@ let pp_var fmt id =
     (if !Options.kind2_print then kind2_protect id.var_id else id.var_id)
     pp_var_type id
 
-let pp_vars fmt vars = fprintf_list ~sep:"; " pp_var fmt vars
+let pp_vars fmt vars = pp_print_list ~pp_sep:pp_print_semicolon pp_var fmt vars
 
 let pp_quantifiers fmt (q, vars) =
   match q with
@@ -102,9 +102,10 @@ and pp_const fmt c =
   | Const_tag t ->
     pp_print_string fmt t
   | Const_array ca ->
-    fprintf fmt "[%a]" (Utils.fprintf_list ~sep:"," pp_const) ca
+    fprintf fmt "[%a]" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt ",")
+                          pp_const) ca
   | Const_struct fl ->
-    fprintf fmt "{%a }" (Utils.fprintf_list ~sep:" " pp_struct_const_field) fl
+    fprintf fmt "{%a }" (pp_print_list pp_struct_const_field) fl
   (* used only for annotations *)
   | Const_string s ->
     pp_print_string fmt ("\"" ^ s ^ "\"")
@@ -118,7 +119,8 @@ let pp_annot_key fmt kwds =
   | [ x ] ->
     pp_print_string fmt x
   | _ ->
-    fprintf fmt "/%a/" (fprintf_list ~sep:"/" pp_print_string) kwds
+    fprintf fmt "/%a/" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt "/")
+                          pp_print_string) kwds
 
 let pp_kind2_when fmt (id, l) =
   if l = "true" then fprintf fmt "%s" id
@@ -141,9 +143,9 @@ let rec pp_expr fmt expr =
         | Expr_array a ->
           fprintf fmt "[%a]" pp_tuple a
         | Expr_access (a, d) ->
-          fprintf fmt "%a[%a]" pp_expr a Dimension.pp_dimension d
+          fprintf fmt "%a[%a]" pp_expr a Dimension.pp d
         | Expr_power (a, d) ->
-          fprintf fmt "(%a^%a)" pp_expr a Dimension.pp_dimension d
+          fprintf fmt "(%a^%a)" pp_expr a Dimension.pp d
         | Expr_tuple el ->
           fprintf fmt "(%a)" pp_tuple el
         | Expr_ite (c, t, e) ->
@@ -169,11 +171,12 @@ let rec pp_expr fmt expr =
         Format.fprintf fmt "%t: %a" pp Types.print_ty expr.expr_type
       else pp fmt)
 
-and pp_tuple fmt el = fprintf_list ~sep:"," pp_expr fmt el
+and pp_tuple fmt el = pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt ",")
+    pp_expr fmt el
 
 and pp_handler fmt (t, h) = fprintf fmt "(%s -> %a)" t pp_expr h
 
-and pp_handlers fmt hl = fprintf_list ~sep:" " pp_handler fmt hl
+and pp_handlers fmt hl = pp_print_list pp_handler fmt hl
 
 and pp_app fmt id e r =
   if !Options.kind2_print && not (List.mem id Basic_library.internal_funs) then
@@ -273,7 +276,7 @@ and pp_call fmt id e =
 
 and pp_eexpr fmt e =
   fprintf fmt "%a%t %a"
-    (Utils.fprintf_list ~sep:"; " pp_quantifiers)
+    (pp_print_list ~pp_sep:pp_print_semicolon pp_quantifiers)
     e.eexpr_quantifiers
     (fun fmt ->
       match e.eexpr_quantifiers with [] -> () | _ -> fprintf fmt ";")
@@ -297,22 +300,23 @@ and pp_s_function fmt expr_ann =
         | [ x ] ->
           pp_print_string fmt x
         | _ ->
-          fprintf fmt "%a" (fprintf_list ~sep:"/" pp_print_string) kwds)
+          fprintf fmt "%a" (pp_print_list ~pp_sep:(fun fmt () -> pp_print_string fmt "/")
+                              pp_print_string) kwds)
       pp_sf_value ee
   in
-  fprintf_list ~sep:"@ " pp_annot fmt expr_ann.annots
+  pp_print_list pp_annot fmt expr_ann.annots
 
 and pp_expr_annot fmt expr_ann =
   let pp_annot fmt (kwds, ee) =
     fprintf fmt "(*!%a: %a; *)" pp_annot_key kwds pp_eexpr ee
   in
-  fprintf_list ~sep:"@ " pp_annot fmt expr_ann.annots
+  pp_print_list pp_annot fmt expr_ann.annots
 
 let pp_asserts fmt asserts =
   match asserts with
   | _ :: _ ->
     fprintf fmt "(* Asserts definitions *)@ ";
-    fprintf_list ~sep:"@ "
+    pp_print_list
       (fun fmt assert_ ->
         let expr = assert_.assert_expr in
         fprintf fmt "assert %a;" pp_expr expr)
@@ -334,7 +338,7 @@ let pp_node_var fmt id =
   | Some v ->
     fprintf fmt " = %a" pp_expr v
 
-let pp_node_args = fprintf_list ~sep:";@ " pp_node_var
+let pp_node_args = pp_print_list ~pp_sep:pp_print_semicolon pp_node_var
 
 let pp_node_eq fmt eq =
   fprintf fmt "%a = %a;" pp_eq_lhs eq.eq_lhs pp_expr eq.eq_rhs
@@ -351,7 +355,7 @@ let pp_until fmt (_, expr, restart, st) =
 let rec pp_handler fmt handler =
   fprintf fmt "state %s:@ @[<v 2>  %a%t%alet@,@[<v 2>  %a@ %a@ %a@]@,tel@ %a@]"
     handler.hand_state
-    (Utils.fprintf_list ~sep:"@ " pp_unless)
+    (pp_print_list pp_unless)
     handler.hand_unless
     (fun fmt -> if not ([] = handler.hand_unless) then fprintf fmt "@ ")
     (fun fmt locals ->
@@ -360,14 +364,13 @@ let rec pp_handler fmt handler =
         ()
       | _ ->
         fprintf fmt "@[<v 4>var %a@]@ "
-          (Utils.fprintf_list ~sep:"@ " (fun fmt v ->
-               fprintf fmt "%a;" pp_node_var v))
+          (pp_print_list ~pp_sep:pp_print_semicolon pp_node_var)
           locals)
     handler.hand_locals
-    (fprintf_list ~sep:"@ " pp_expr_annot)
+    (pp_print_list pp_expr_annot)
     handler.hand_annots pp_node_stmts handler.hand_stmts pp_asserts
     handler.hand_asserts
-    (Utils.fprintf_list ~sep:"@," pp_until)
+    (pp_print_list pp_until)
     handler.hand_until
 
 and pp_node_stmt fmt stmt =
@@ -379,10 +382,10 @@ and pp_node_stmts fmt stmts =
 
 and pp_node_aut fmt aut =
   fprintf fmt "@[<v 0>automaton %s@,%a@]" aut.aut_id
-    (Utils.fprintf_list ~sep:"@ " pp_handler)
+    (pp_print_list pp_handler)
     aut.aut_handlers
 
-and pp_node_eqs fmt eqs = fprintf_list ~sep:"@ " pp_node_eq fmt eqs
+and pp_node_eqs fmt eqs = pp_print_list pp_node_eq fmt eqs
 
 let pp_typedef fmt ty =
   fprintf fmt "type %s = %a;" ty.tydef_id pp_var_type_dec_desc ty.tydef_desc
@@ -420,7 +423,7 @@ let pp_spec_stmt fmt stmt =
 let pp_spec fmt spec =
   (* const are prefixed with const in pp_var and with nothing for regular
      variables. We adapt the call to produce the appropriate output. *)
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt v ->
       fprintf fmt "%a = %t;" pp_var v (fun fmt ->
           match v.var_dec_value with
@@ -430,26 +433,26 @@ let pp_spec fmt spec =
             pp_expr fmt e))
     fmt spec.consts;
 
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt s -> pp_spec_stmt fmt s)
     fmt spec.stmts;
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt r -> fprintf fmt "assume %a;" pp_eexpr r)
     fmt spec.assume;
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt r -> fprintf fmt "guarantee %a;" pp_eexpr r)
     fmt spec.guarantees;
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt mode ->
       fprintf fmt "mode %s (@[<v 0>%a@ %a@]);" mode.mode_id
-        (fprintf_list ~eol:"" ~sep:"@ " (fun fmt r ->
+        (pp_print_list (fun fmt r ->
              fprintf fmt "require %a;" pp_eexpr r))
         mode.require
-        (fprintf_list ~eol:"" ~sep:"@ " (fun fmt r ->
+        (pp_print_list (fun fmt r ->
              fprintf fmt "ensure %a;" pp_eexpr r))
         mode.ensure)
     fmt spec.modes;
-  fprintf_list ~eol:"@, " ~sep:"@, "
+  pp_print_list
     (fun fmt import ->
       fprintf fmt "import %s (%a) returns (%a);" import.import_nodeid pp_expr
         import.inputs pp_expr import.outputs)
@@ -495,7 +498,7 @@ let pp_spec_as_comment fmt (inl, outl, spec) =
   | NodeSpec name ->
     (* Pushing stmts in contract. We update the original information with the
        computed one in nd. *)
-    let pp_l = fprintf_list ~sep:"," pp_var_name in
+    let pp_l = pp_comma_list pp_var_name in
     fprintf fmt "@[<hov 2>(*@contract import %s(%a) returns (%a); @]*)@ " name
       pp_l inl pp_l outl
 
@@ -526,7 +529,7 @@ let pp_node fmt nd =
         ()
       | _ ->
         fprintf fmt "@[<v 4>var %a@]@ "
-          (fprintf_list ~sep:"@ " (fun fmt v -> fprintf fmt "%a;" pp_node_var v))
+          (pp_print_list (fun fmt v -> fprintf fmt "%a;" pp_node_var v))
           locals)
     nd.node_locals;
   (* Checks *)
@@ -537,14 +540,14 @@ let pp_node fmt nd =
         ()
       | _ ->
         fprintf fmt "@[<v 4>check@ %a@]@ "
-          (fprintf_list ~sep:"@ " (fun fmt d ->
-               fprintf fmt "%a" Dimension.pp_dimension d))
+          (pp_print_list (fun fmt d ->
+               fprintf fmt "%a" Dimension.pp d))
           checks)
     nd.node_checks;
   (* Body *)
   fprintf fmt "@[<v 2>let@ ";
   (* Annotations *)
-  fprintf fmt "%a" (fprintf_list ~sep:"@ " pp_expr_annot) nd.node_annot;
+  fprintf fmt "%a" (pp_print_list pp_expr_annot) nd.node_annot;
   (* Statements *)
   fprintf fmt "%a" pp_node_stmts nd.node_stmts;
   (* Asserts *)
@@ -589,7 +592,7 @@ let pp_const_decl fmt cdecl =
   fprintf fmt "%s = %a;" cdecl.const_id pp_const cdecl.const_value
 
 let pp_const_decl_list fmt clist =
-  fprintf_list ~sep:"@ " pp_const_decl fmt clist
+  pp_print_list pp_const_decl fmt clist
 
 let pp_decl fmt decl =
   match decl.top_decl_desc with
@@ -676,13 +679,13 @@ let pp_lusi_header fmt basename prog =
 let pp_offset fmt offset =
   match offset with
   | Index i ->
-    fprintf fmt "[%a]" Dimension.pp_dimension i
+    fprintf fmt "[%a]" Dimension.pp i
   | Field f ->
     fprintf fmt ".%s" f
 
 let pp_node_list fmt prog =
   Format.fprintf fmt "@[<h 2>%a@]"
-    (fprintf_list ~sep:"@ " (fun fmt decl ->
+    (pp_print_list (fun fmt decl ->
          match decl.top_decl_desc with
          | Node nd ->
            Format.fprintf fmt "%s" nd.node_id
diff --git a/src/printers.mli b/src/printers.mli
new file mode 100644
index 00000000..6d4f55c4
--- /dev/null
+++ b/src/printers.mli
@@ -0,0 +1,17 @@
+open Format
+open Lustre_types
+
+val pp_expr: formatter -> expr -> unit
+val pp_eexpr: formatter -> eexpr -> unit
+val pp_node: formatter -> node_desc -> unit
+val pp_const: formatter -> constant -> unit
+val pp_var: formatter -> var_decl -> unit
+val pp_node_eq: formatter -> eq -> unit
+val pp_node_eqs: formatter -> eq list -> unit
+val pp_spec: formatter -> contract_desc -> unit
+val pp_expr_annot: formatter -> expr_annot -> unit
+val pp_short_decl: formatter -> top_decl -> unit
+val pp_const_decl: formatter -> const_desc -> unit
+val pp_var_type_dec_desc: formatter -> type_dec_desc -> unit
+val pp_typedef: formatter -> typedef_desc -> unit
+val pp_prog: formatter -> program_t -> unit
diff --git a/src/scheduling.ml b/src/scheduling.ml
index ef862735..7fd6ed10 100644
--- a/src/scheduling.ml
+++ b/src/scheduling.ml
@@ -177,10 +177,10 @@ let pp_eq_schedule fmt vl =
   | [] ->
     assert false
   | [ v ] ->
-    Format.fprintf fmt "%s" v
+    Format.pp_print_string fmt v
   | _ ->
     Format.fprintf fmt "(%a)"
-      (fprintf_list ~sep:" , " (fun fmt v -> Format.fprintf fmt "%s" v))
+      (Format.pp_comma_list Format.pp_print_string)
       vl
 
 let pp_schedule fmt node_schs =
@@ -223,7 +223,7 @@ let pp_warning_unused fmt node_schs =
             if vu.var_orig then
               Format.fprintf fmt
                 "  Warning: variable '%s' seems unused@,  %a@,@," u
-                Location.pp_loc vu.var_loc)
+                Location.pp vu.var_loc)
           unused)
     node_schs
 
@@ -266,7 +266,7 @@ let sort_equations_from_schedule eqs sch =
       in
       Log.report ~level:1 (fun fmt ->
           Format.fprintf fmt "[Warning] Unused variables: %a@ "
-            (fprintf_list ~sep:", " Format.pp_print_string)
+            (Format.pp_comma_list Format.pp_print_string)
             vars);
       vars)
     else []
diff --git a/src/scheduling.mli b/src/scheduling.mli
new file mode 100644
index 00000000..8d7a6128
--- /dev/null
+++ b/src/scheduling.mli
@@ -0,0 +1,9 @@
+open Utils
+open Lustre_types
+open Scheduling_type
+
+val schedule_prog: program_t -> program_t * schedule_report IMap.t
+val remove_prog_inlined_locals: 'a IMap.t IMap.t -> schedule_report IMap.t -> schedule_report IMap.t
+val compute_prog_reuse_table: schedule_report IMap.t -> (ident, var_decl) Hashtbl.t IMap.t
+
+val sort_equations_from_schedule: eq list -> ident list list -> eq list * ident list
diff --git a/src/scheduling_type.ml b/src/scheduling_type.mli
similarity index 100%
rename from src/scheduling_type.ml
rename to src/scheduling_type.mli
diff --git a/src/sortProg.ml b/src/sortProg.ml
index f46e793a..29f8ad94 100644
--- a/src/sortProg.ml
+++ b/src/sortProg.ml
@@ -50,19 +50,18 @@ let sort prog =
 
   Log.report ~level:3 (fun fmt ->
       Format.fprintf fmt "@ @[<v 2>.. ordered list of declarations:@ %a@]@ "
-        (Utils.fprintf_list ~sep:"@ " Printers.pp_short_decl)
-        sorted);
+        (Format.pp_print_list Printers.pp_short_decl) sorted);
   not_nodes @ sorted
 
-let sort_node_locals nd =
-  { nd with node_locals = Causality.VarClockDep.sort nd.node_locals }
-
 let sort_nodes_locals prog =
   List.map
     (fun top ->
       match top.top_decl_desc with
       | Node nd ->
-        { top with top_decl_desc = Node (sort_node_locals nd) }
+        { top with
+          top_decl_desc = Node
+              { nd with
+                node_locals = Causality.VarClockDep.sort nd.node_locals }}
       | _ ->
         top)
     prog
diff --git a/src/sortProg.mli b/src/sortProg.mli
new file mode 100644
index 00000000..0e614642
--- /dev/null
+++ b/src/sortProg.mli
@@ -0,0 +1,4 @@
+open Lustre_types
+
+val sort_nodes_locals: program_t -> program_t
+val sort: program_t -> program_t
diff --git a/src/spec.mli b/src/spec.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/spec_common.mli b/src/spec_common.mli
new file mode 100644
index 00000000..5d285ca5
--- /dev/null
+++ b/src/spec_common.mli
@@ -0,0 +1,19 @@
+open Utils
+open Lustre_types
+open Spec_types
+
+val mk_conditional_tr: 'a -> 'a formula_t -> 'a formula_t -> 'a formula_t
+
+val mk_branch_tr: var_decl -> (ident * 'a formula_t) list -> 'a formula_t
+
+val mk_assign_tr: var_decl -> 'a -> 'a formula_t
+
+val mk_memory_pack: ?i:int -> ?inst:ident -> ident -> 'a formula_t
+
+val mk_transition: ?mems:ISet.t -> ?insts:ident IMap.t -> ?r:'a -> ?i:int -> ?inst:ident -> ident -> 'a list -> 'a formula_t
+
+val mk_state_variable_pack: var_decl -> 'a formula_t
+
+val mk_state_assign_tr: var_decl -> 'a -> 'a formula_t
+
+val red: 'a formula_t -> 'a formula_t
diff --git a/src/spec_types.ml b/src/spec_types.ml
index fc3dfeed..4980309b 100644
--- a/src/spec_types.ml
+++ b/src/spec_types.ml
@@ -1,3 +1,4 @@
+open Utils
 open Lustre_types
 
 type register_t = ResetFlag | StateVar of var_decl
@@ -13,7 +14,7 @@ type ('a, _) expression_t =
   | Memory : register_t -> ('a, left_v) expression_t
 
 (** TODO: why moving this elsewhere makes the exhaustiveness check fail? *)
-let type_of_l_value : type a. (a, left_v) expression_t -> Types.type_expr =
+let type_of_l_value : type a. (a, left_v) expression_t -> Types.t =
   function
   | Var v ->
     v.var_type
diff --git a/src/spec_types.mli b/src/spec_types.mli
new file mode 100644
index 00000000..8301141d
--- /dev/null
+++ b/src/spec_types.mli
@@ -0,0 +1,66 @@
+open Utils
+open Lustre_types
+
+type register_t = ResetFlag | StateVar of var_decl
+
+type left_v
+
+type right_v
+
+type ('a, _) expression_t =
+  | Val : 'a -> ('a, right_v) expression_t
+  | Tag : ident -> ('a, right_v) expression_t
+  | Var : var_decl -> ('a, left_v) expression_t
+  | Memory : register_t -> ('a, left_v) expression_t
+
+val type_of_l_value: ('a, left_v) expression_t -> Types.t
+
+type 'a predicate_t =
+  | Transition :
+      ident (* node name *)
+      * ident option
+      (* instance *)
+      * int option
+      (* transition index *)
+      * ('a, 'b) expression_t list
+      (* variables *)
+      * bool (* reset *)
+      * Utils.ISet.t (* memory footprint *)
+      * ident Utils.IMap.t
+      (* memory instances footprint *)
+      -> 'a predicate_t
+  | Reset of ident * ident * 'a
+  | MemoryPack of ident * ident option * int option
+  | Initialization
+  | ResetCleared of ident
+
+type 'a formula_t =
+  | True
+  | False
+  | Equal : ('a, left_v) expression_t * ('a, 'b) expression_t -> 'a formula_t
+  | And of 'a formula_t list
+  | Or of 'a formula_t list
+  | Imply of 'a formula_t * 'a formula_t
+  | Exists of var_decl list * 'a formula_t
+  | Forall of var_decl list * 'a formula_t
+  | Ternary :
+      ('a, 'b) expression_t * 'a formula_t * 'a formula_t
+      -> 'a formula_t
+  | Predicate : 'a predicate_t -> 'a formula_t
+  | StateVarPack of register_t
+  | ExistsMem of ident * 'a formula_t * 'a formula_t
+
+type 'a transition_t = {
+  tname : node_desc;
+  tindex : int option;
+  tvars : var_decl list;
+  tformula : 'a formula_t;
+  tmem_footprint : Utils.ISet.t;
+  tinst_footprint : ident Utils.IMap.t;
+}
+
+type 'a memory_pack_t = {
+  mpname : node_desc;
+  mpindex : int option;
+  mpformula : 'a formula_t;
+}
diff --git a/src/splitting.mli b/src/splitting.mli
new file mode 100644
index 00000000..96c139b4
--- /dev/null
+++ b/src/splitting.mli
@@ -0,0 +1,5 @@
+open Lustre_types
+
+val tuple_split_eq: eq -> eq list
+
+val tuple_split_eq_list: eq list -> eq list
diff --git a/src/tools/importer/main_lustre_importer.mli b/src/tools/importer/main_lustre_importer.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/importer/vhdl_deriving_yojson.mli b/src/tools/importer/vhdl_deriving_yojson.mli
new file mode 100644
index 00000000..7825694d
--- /dev/null
+++ b/src/tools/importer/vhdl_deriving_yojson.mli
@@ -0,0 +1,294 @@
+type vhdl_type_t =
+  | Base of string
+  | Range of string option * int * int [@name "RANGE_WITH_DIRECTION"]
+  | Bit_vector of int * int
+  | Array of int * int * vhdl_type_t
+  | Enumerated of string list
+  | Void
+[@@deriving yojson]
+
+(************************************************************************************)
+(* Constants *)
+(************************************************************************************)
+
+(* TODO: do we need more constructors ? *)
+type cst_val_t =
+  | CstInt of int
+  | CstStdLogic of string
+  | CstLiteral of string [@name "CST_LITERAL"]
+[@@deriving yojson { strict = false }]
+
+type vhdl_subtype_indication_t = {
+  name : string;
+  definition : vhdl_type_t option; [@default Some Void]
+}
+[@@deriving yojson { strict = false }]
+
+(* TODO ? Shall we merge definition / declaration *)
+type vhdl_definition_t =
+  | Type of { name : string; definition : vhdl_type_t }
+      [@name "TYPE_DECLARATION"]
+  | Subtype of { name : string; typ : vhdl_subtype_indication_t }
+      [@name "SUBTYPE_DECLARATION"]
+[@@deriving yojson { strict = false }]
+
+type vhdl_declaration_t =
+  | VarDecl of {
+      names : string list;
+      typ : vhdl_subtype_indication_t;
+      init_val : cst_val_t option; [@default Some (CstInt 0)]
+    } [@name "VARIABLE_DECLARATION"]
+  | CstDecl of {
+      names : string list;
+      typ : vhdl_subtype_indication_t;
+      init_val : cst_val_t;
+    } [@name "CONSTANT_DECLARATION"]
+  | SigDecl of {
+      names : string list;
+      typ : vhdl_subtype_indication_t;
+      init_val : cst_val_t option; [@default Some (CstInt 0)]
+    } [@name "SIGNAL_DECLARATION"]
+[@@deriving yojson { strict = false }]
+
+(************************************************************************************)
+(* Attributes for types, arrays, signals and strings *)
+(************************************************************************************)
+
+type 'basetype vhdl_type_attributes_t =
+  | TAttNoArg of { id : string }
+  | TAttIntArg of { id : string; arg : int }
+  | TAttValArg of { id : string; arg : 'basetype }
+  | TAttStringArg of { id : string; arg : string }
+[@@deriving yojson { strict = false }]
+
+type vhdl_array_attributes_t =
+  | AAttInt of { id : string; arg : int }
+  | AAttAscending
+[@@deriving yojson { strict = false }]
+
+type vhdl_signal_attributes_t = SigAtt of string
+[@@deriving yojson { strict = false }]
+
+type vhdl_string_attributes_t = StringAtt of string
+[@@deriving yojson { strict = false }]
+
+(************************************************************************************)
+(* Expressions / Statements *)
+(************************************************************************************)
+type suffix_selection_t = Idx of int | Range of int * int
+[@@deriving yojson { strict = false }]
+
+type vhdl_expr_t =
+  | Call of vhdl_name_t [@name "CALL"]
+  | Cst of cst_val_t [@name "CONSTANT_VALUE"]
+  | Op of { id : string; [@default ""] args : vhdl_expr_t list [@default []] }
+      [@name "EXPRESSION"]
+  | IsNull [@name "IsNull"]
+  | Time of { value : int; phy_unit : string [@default ""] }
+  | Sig of { name : string; att : vhdl_signal_attributes_t option }
+  | SuffixMod of { expr : vhdl_expr_t; selection : suffix_selection_t }
+[@@deriving yojson { strict = false }]
+
+and vhdl_name_t =
+  | Simple of string [@name "SIMPLE_NAME"]
+  | Selected of vhdl_name_t list [@name "SELECTED_NAME"]
+  | Index of { id : vhdl_name_t; exprs : vhdl_expr_t list }
+      [@name "INDEXED_NAME"]
+  | Slice of { id : vhdl_name_t; range : vhdl_type_t } [@name "SLICE_NAME"]
+  | Attribute of {
+      id : vhdl_name_t;
+      designator : vhdl_name_t;
+      expr : vhdl_expr_t; [@default IsNull]
+    } [@name "ATTRIBUTE_NAME"]
+  | Function of { id : vhdl_name_t; assoc_list : vhdl_assoc_element_t list }
+      [@name "FUNCTION_CALL"]
+  | NoName
+[@@deriving yojson { strict = false }]
+
+and vhdl_assoc_element_t = {
+  formal_name : vhdl_name_t option; [@default Some NoName]
+  formal_arg : vhdl_name_t option; [@default Some NoName]
+  actual_name : vhdl_name_t option; [@default Some NoName]
+  actual_designator : vhdl_name_t option; [@default Some NoName]
+  actual_expr : vhdl_expr_t option; [@default Some IsNull]
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_sequential_stmt_t =
+  | VarAssign of { lhs : vhdl_name_t; rhs : vhdl_expr_t }
+  | SigSeqAssign of {
+      label : string; [@default ""]
+      lhs : vhdl_name_t;
+      rhs : vhdl_expr_t list;
+    } [@name "SIGNAL_ASSIGNMENT_STATEMENT"]
+  | If of {
+      label : string; [@default ""]
+      if_cases : vhdl_if_case_t list;
+      default : vhdl_sequential_stmt_t list; [@default []]
+    } [@name "IF_STATEMENT"]
+  | Case of { guard : vhdl_expr_t; branches : vhdl_case_item_t list }
+      [@name "CASE_STATEMENT_TREE"]
+  | Exit of {
+      label : string; [@default ""]
+      loop_label : string option; [@default Some ""]
+      condition : vhdl_expr_t option; [@default Some IsNull]
+    } [@name "EXIT_STATEMENT"]
+  | Assert of {
+      label : string; [@default ""]
+      cond : vhdl_expr_t;
+      report : vhdl_expr_t; [@default IsNull]
+      severity : vhdl_expr_t; [@default IsNull]
+    } [@name "ASSERTION_STATEMENT"]
+  | Wait [@name "WAIT_STATEMENT"]
+  | Null of { label : string [@default ""] } [@name "NULL_STATEMENT"]
+
+and vhdl_if_case_t = {
+  if_cond : vhdl_expr_t;
+  if_block : vhdl_sequential_stmt_t list;
+}
+
+and vhdl_case_item_t = {
+  when_cond : vhdl_expr_t list;
+  when_stmt : vhdl_sequential_stmt_t list;
+}
+[@@deriving yojson { strict = false }]
+
+type signal_condition_t = {
+  expr : vhdl_expr_t list;
+  (* when expression *)
+  cond : vhdl_expr_t; [@default IsNull]
+      (* optional else case expression. If None, could be a latch *)
+}
+[@@deriving yojson { strict = false }]
+
+type signal_selection_t = {
+  expr : vhdl_expr_t;
+  when_sel : vhdl_expr_t list; [@default []]
+}
+[@@deriving yojson { strict = false }]
+
+type conditional_signal_t = {
+  postponed : bool; [@default false]
+  label : string option; [@default Some ""]
+  lhs : vhdl_name_t;
+  (* assigned signal = target*)
+  rhs : signal_condition_t list;
+  (* expression *)
+  cond : vhdl_expr_t; [@default IsNull]
+  delay : vhdl_expr_t; [@default IsNull]
+}
+[@@deriving yojson { strict = false }]
+
+type process_t = {
+  id : string option; [@default Some ""]
+  declarations : vhdl_declaration_t list option;
+      [@key "PROCESS_DECLARATIVE_PART"] [@default Some []]
+  active_sigs : vhdl_name_t list; [@default []]
+  body : vhdl_sequential_stmt_t list;
+      [@key "PROCESS_STATEMENT_PART"] [@default []]
+}
+[@@deriving yojson { strict = false }]
+
+type selected_signal_t = {
+  postponed : bool; [@default false]
+  label : string option; [@default Some ""]
+  lhs : vhdl_name_t;
+  (* assigned signal = target *)
+  sel : vhdl_expr_t;
+  branches : signal_selection_t list; [@default []]
+  delay : vhdl_expr_t option;
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_concurrent_stmt_t =
+  | SigAssign of conditional_signal_t [@name "CONDITIONAL_SIGNAL_ASSIGNMENT"]
+  | Process of process_t [@name "PROCESS_STATEMENT"]
+  | SelectedSig of selected_signal_t [@name "SELECTED_SIGNAL_ASSIGNMENT"]
+[@@deriving yojson { strict = false }]
+
+(* type vhdl_statement_t =
+
+   (* | DeclarationStmt of declaration_stmt_t *) | ConcurrentStmt of
+   vhdl_concurrent_stmt_t | SequentialStmt of vhdl_sequential_stmt_t *)
+
+(************************************************************************************)
+(* Entities *)
+(************************************************************************************)
+
+(* TODO? Seems to appear optionally in entities *)
+type vhdl_generic_t = unit [@@deriving yojson { strict = false }]
+
+type vhdl_port_kind_t =
+  | InPort [@name "in"]
+  | OutPort [@name "out"]
+  | InoutPort [@name "inout"]
+  | BufferPort [@name "buffer"]
+[@@deriving yojson]
+
+type vhdl_port_t = {
+  names : string list; [@default []]
+  kind : vhdl_port_kind_t;
+  typ : string; (* typ: vhdl_type_t; *)
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_entity_t = {
+  name : string; [@default ""]
+  generics : vhdl_generic_t list option;
+      [@key "GENERIC_CLAUSE"] [@default Some []]
+  ports : vhdl_port_t list; [@key "PORT_CLAUSE"] [@default []]
+}
+[@@deriving yojson { strict = false }]
+
+(************************************************************************************)
+(* Packages / Library loading *)
+(************************************************************************************)
+
+(* Optional. Describes shared definitions *)
+type vhdl_package_t = {
+  name : string; [@default ""]
+  shared_defs : vhdl_definition_t list; [@default []]
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_load_t =
+  | Library of string list [@name "LIBRARY_CLAUSE"] [@default ""]
+  | Use of string list [@name "USE_CLAUSE"] [@default []]
+[@@deriving yojson]
+
+(************************************************************************************)
+(* Architecture / VHDL Design *)
+(************************************************************************************)
+
+type vhdl_architecture_t = {
+  name : string; [@default ""]
+  entity : string; [@default ""]
+  declarations : vhdl_declaration_t list option;
+      [@key "ARCHITECTURE_DECLARATIVE_PART"] [@default Some []]
+  body : vhdl_concurrent_stmt_t list option;
+      [@key "ARCHITECTURE_STATEMENT_PART"] [@default Some []]
+}
+[@@deriving yojson { strict = false }]
+
+(* TODO. Configuration is optional *)
+type vhdl_configuration_t = unit [@@deriving yojson { strict = false }]
+
+type vhdl_design_t = {
+  packages : vhdl_package_t list; [@key "PACKAGE_DECLARATION"] [@default []]
+  libraries : vhdl_load_t list option;
+      [@key "CONTEXT_CLAUSE"] [@default Some []]
+  entities : vhdl_entity_t list; [@key "ENTITY_DECLARATION"] [@default []]
+  architectures : vhdl_architecture_t list;
+      [@key "ARCHITECTURE_BODY"] [@default []]
+  configuration : vhdl_configuration_t option;
+      [@key "CONFIGURATION_DECLARATION"] [@default Some ()]
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_design_file_t = {
+  design_unit : vhdl_design_t list; [@key "DESIGN_UNIT"] [@default []]
+}
+[@@deriving yojson { strict = false }]
+
+type vhdl_file_t = { design_file : vhdl_design_file_t [@key "DESIGN_FILE"] }
+[@@deriving yojson]
diff --git a/src/tools/importer/vhdl_json_lib.mli b/src/tools/importer/vhdl_json_lib.mli
new file mode 100644
index 00000000..f5f59f9a
--- /dev/null
+++ b/src/tools/importer/vhdl_json_lib.mli
@@ -0,0 +1,8 @@
+open Yojson.Safe
+
+val prune_str: string -> t -> t
+val prune_null_assoc: t -> t
+val to_list_content_str: string -> t -> t
+val flatten_ivd: t -> t
+val flatten_numeric_literal: t -> t
+val to_list_str: string -> t -> t
diff --git a/src/tools/seal/seal_export.mli b/src/tools/seal/seal_export.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/seal/seal_extract.mli b/src/tools/seal/seal_extract.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/seal/seal_slice.mli b/src/tools/seal/seal_slice.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/seal/seal_utils.mli b/src/tools/seal/seal_utils.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/seal/seal_verifier.mli b/src/tools/seal/seal_verifier.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/stateflow/sf_sem.mli b/src/tools/stateflow/sf_sem.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/tiny/tiny_utils.mli b/src/tools/tiny/tiny_utils.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/tiny/tiny_verifier.mli b/src/tools/tiny/tiny_verifier.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_analyze.mli b/src/tools/zustre/zustre_analyze.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_cex.mli b/src/tools/zustre/zustre_cex.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_common.mli b/src/tools/zustre/zustre_common.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_data.mli b/src/tools/zustre/zustre_data.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_test.mli b/src/tools/zustre/zustre_test.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tools/zustre/zustre_verifier.mli b/src/tools/zustre/zustre_verifier.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/type_predef.ml b/src/type_predef.ml
index c550c963..9cb281ba 100644
--- a/src/type_predef.ml
+++ b/src/type_predef.ml
@@ -74,13 +74,13 @@ module Make (T : Types.S) = struct
     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 d = Dimension.mkdim Location.dummy Dimension.Dunivar in
+    let d' = Dimension.mkdim Location.dummy 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 d = Dimension.mkdim Location.dummy Dimension.Dunivar in
     let univ = new_univar () in
     type_arrow (type_tuple [ univ; type_static d type_int ]) (type_array d univ)
 end
@@ -93,7 +93,7 @@ end
 (*   let type_string_builder = Tbasic Basic.Tstring *)
 (* end *)
 
-module Main = Make (Types.Main)
+module Main = Make (Types)
 include Main
 
 (* Local Variables: *)
diff --git a/src/type_predef.mli b/src/type_predef.mli
new file mode 100644
index 00000000..a8d57a57
--- /dev/null
+++ b/src/type_predef.mli
@@ -0,0 +1,32 @@
+open Utils
+(* open Types *)
+
+module Make(T: Types.S) : sig
+  (* see https://stackoverflow.com/a/37307124 *)
+  include module type of struct include T end
+  val type_int: t
+  val type_real: t
+  val type_bool: t
+  val type_string: t
+  val type_clock: t -> t
+  val type_const: ident -> t
+  val type_enum: ident list -> t
+  val type_struct: (ident * t) list -> t
+  val type_arrow: t -> t -> t
+  val type_array: Dimension.t -> t -> t
+  val type_static: Dimension.t -> t -> t
+end
+
+(* include Types.S *)
+val type_int: Types.t
+val type_bool: Types.t
+val type_real: Types.t
+val type_const: ident -> Types.t
+val type_static: Dimension.t -> Types.t -> Types.t
+val type_bin_poly_op: Types.t
+val type_unary_poly_op: Types.t
+val type_bin_int_op: Types.t
+val type_bin_bool_op: Types.t
+val type_bin_comp_op: Types.t
+val type_unary_bool_op: Types.t
+val type_tuple: Types.t list -> Types.t
diff --git a/src/types.ml b/src/types.ml
index f9582629..558b68e6 100644
--- a/src/types.ml
+++ b/src/types.ml
@@ -14,8 +14,6 @@
 open Utils
 (** Types definitions and a few utility functions on types. *)
 
-open Dimension
-
 module type BASIC_TYPES = sig
   type t
 
@@ -48,7 +46,127 @@ module type BASIC_TYPES = sig
   val is_unifiable : t -> t -> bool
 end
 
-module Basic = struct
+module type S = sig
+  module BasicT : BASIC_TYPES
+
+  type basic_type = BasicT.t
+
+  type t = { mutable tdesc: type_desc; tid: int }
+
+  and type_desc =
+    | Tconst of ident
+    (* type constant *)
+    | Tbasic of basic_type
+    | Tclock of t
+    (* A type expression explicitely tagged as carrying a clock *)
+    | Tarrow of t * t
+    | Ttuple of t list
+    | Tenum of ident list
+    | Tstruct of (ident * t) list
+    | Tarray of Dimension.t * t
+    | Tstatic of Dimension.t * t
+    (* a type carried by a dimension expression *)
+    | Tlink of t
+    (* 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 t * t
+    | Poly_imported_node of ident
+
+  exception Unify of t * t
+
+  exception Error of Location.t * error
+
+  val is_real_type : t -> bool
+
+  val is_int_type : t -> bool
+
+  val is_bool_type : t -> bool
+
+  val is_const_type : t -> ident -> bool
+
+  val is_static_type : t -> bool
+
+  val is_array_type : t -> bool
+
+  val is_dimension_type : t -> bool
+
+  val is_address_type : t -> bool
+
+  val is_generic_type : t -> bool
+
+  val print_ty : Format.formatter -> t -> unit
+
+  val repr : t -> t
+
+  val dynamic_type : t -> t
+
+  val type_desc : t -> type_desc
+
+  val new_var : unit -> t
+
+  val new_univar : unit -> t
+
+  val new_ty : type_desc -> t
+
+  val type_int : type_desc
+
+  val type_real : type_desc
+
+  val type_bool : type_desc
+
+  val type_string : type_desc
+
+  val array_element_type : t -> t
+
+  val type_list_of_type : t -> t list
+
+  val print_node_ty : Format.formatter -> t -> unit
+
+  val get_clock_base_type : t -> t option
+
+  val get_static_value : t -> Dimension.t option
+
+  val is_tuple_type : t -> bool
+
+  val type_of_type_list : t list -> t
+
+  val split_arrow : t -> t * t
+
+  val unclock_type : t -> t
+
+  val bottom : t
+
+  val map_tuple_type : (t -> t) -> t -> t
+
+  val array_base_type : t -> t
+
+  val array_type_dimension : t -> Dimension.t
+
+  val pp_error : Format.formatter -> error -> unit
+
+  val struct_field_type : t -> ident -> t
+
+  val array_type_multi_dimension : t -> Dimension.t list
+end
+
+module Basic: BASIC_TYPES = struct
   type t = Tstring | Tint | Treal | Tbool | Trat
   (* Actually unused for now. Only place where it can appear is in a clock
      declaration *)
@@ -101,47 +219,27 @@ module Make (BasicT : BASIC_TYPES) = struct
 
   type basic_type = BasicT.t
 
-  type type_expr = { mutable tdesc : type_desc; tid : int }
+  type t = { mutable tdesc: type_desc; tid: int }
 
   and type_desc =
     | Tconst of ident
     (* type constant *)
     | Tbasic of basic_type
-    | Tclock of type_expr
+    | Tclock of t
     (* A type expression explicitely tagged as carrying a clock *)
-    | Tarrow of type_expr * type_expr
-    | Ttuple of type_expr list
+    | Tarrow of t * t
+    | Ttuple of t list
     | Tenum of ident list
-    | Tstruct of (ident * type_expr) list
-    | Tarray of dim_expr * type_expr
-    | Tstatic of dim_expr * type_expr
+    | Tstruct of (ident * t) list
+    | Tarray of Dimension.t * t
+    | Tstatic of Dimension.t * t
     (* a type carried by a dimension expression *)
-    | Tlink of type_expr
+    | Tlink of t
     (* 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 *\) *)
+    (* Polymorphic type variable *)
 
   type error =
     | Unbound_value of ident
@@ -156,10 +254,10 @@ module Make (BasicT : BASIC_TYPES) = struct
     | WrongArity of int * int
     | WrongMorphism of int * int
     | Type_mismatch of ident
-    | Type_clash of type_expr * type_expr
+    | Type_clash of t * t
     | Poly_imported_node of ident
 
-  exception Unify of type_expr * type_expr
+  exception Unify of t * t
 
   exception Error of Location.t * error
 
@@ -189,17 +287,20 @@ module Make (BasicT : BASIC_TYPES) = struct
     | Tarrow (ty1, ty2) ->
       fprintf fmt "%a -> %a" print_ty ty1 print_ty ty2
     | Ttuple tylist ->
-      fprintf fmt "(%a)" (Utils.fprintf_list ~sep:" * " print_ty) tylist
+      fprintf fmt "(%a)"
+        (pp_print_list
+           ~pp_sep:(fun fmt () -> pp_print_string  fmt " * ") print_ty) tylist
     | Tenum taglist ->
       fprintf fmt "enum {%a }"
-        (Utils.fprintf_list ~sep:", " pp_print_string)
+        (pp_comma_list pp_print_string)
         taglist
     | Tstruct fieldlist ->
       fprintf fmt "struct {%a }"
-        (Utils.fprintf_list ~sep:"; " (print_struct_ty_field pp_basic))
+        (pp_print_list ~pp_sep:pp_print_semicolon
+           (print_struct_ty_field pp_basic))
         fieldlist
     | Tarray (e, ty) ->
-      fprintf fmt "%a^%a" print_ty ty Dimension.pp_dimension e
+      fprintf fmt "%a^%a" print_ty ty Dimension.pp e
     | Tlink ty ->
       print_ty fmt ty
     | Tunivar ->
@@ -227,17 +328,18 @@ module Make (BasicT : BASIC_TYPES) = struct
     | Tarrow (ty1, ty2) ->
       fprintf fmt "%a -> %a" print_node_ty ty1 print_node_ty ty2
     | Ttuple tylist ->
-      fprintf fmt "(%a)" (Utils.fprintf_list ~sep:"*" print_node_ty) tylist
+      fprintf fmt "(%a)" (pp_print_list
+           ~pp_sep:(fun fmt () -> pp_print_string  fmt "")  print_node_ty) tylist
     | Tenum taglist ->
       fprintf fmt "enum {%a }"
-        (Utils.fprintf_list ~sep:", " pp_print_string)
+        (pp_comma_list pp_print_string)
         taglist
     | Tstruct fieldlist ->
       fprintf fmt "struct {%a }"
-        (Utils.fprintf_list ~sep:"; " print_node_struct_ty_field)
+        (pp_print_list ~pp_sep:pp_print_semicolon print_node_struct_ty_field)
         fieldlist
     | Tarray (e, ty) ->
-      fprintf fmt "%a^%a" print_node_ty ty Dimension.pp_dimension e
+      fprintf fmt "%a^%a" print_node_ty ty Dimension.pp e
     | Tlink ty ->
       print_node_ty fmt ty
     | Tunivar ->
@@ -267,7 +369,7 @@ module Make (BasicT : BASIC_TYPES) = struct
       fprintf fmt "Definition and declaration of type %s don't agree@." id
     | Undefined_var vset ->
       fprintf fmt "No definition provided for variable(s): %a@."
-        (Utils.fprintf_list ~sep:"," pp_print_string)
+        (pp_comma_list pp_print_string)
         (ISet.elements vset)
     | Declared_but_undefined id ->
       fprintf fmt "%s is declared but not defined@." id
@@ -279,7 +381,7 @@ module Make (BasicT : BASIC_TYPES) = struct
 
   let new_id = ref (-1)
 
-  let rec bottom = { tdesc = Tlink bottom; tid = -666 }
+  let rec bottom: t = { tdesc = Tlink bottom; tid = -666 }
 
   let new_ty desc =
     incr new_id;
@@ -419,7 +521,7 @@ module Make (BasicT : BASIC_TYPES) = struct
     | Tarray (d, _) ->
       d
     | _ ->
-      Format.eprintf "internal error: Types.array_type_dimension %a@." print_ty
+      eprintf "internal error: Types.array_type_dimension %a@." print_ty
         ty;
       assert false
 
@@ -435,7 +537,7 @@ module Make (BasicT : BASIC_TYPES) = struct
     | Tarray (_, ty') ->
       ty'
     | _ ->
-      Format.eprintf "internal error: Types.array_element_type %a@." print_ty ty;
+      eprintf "internal error: Types.array_element_type %a@." print_ty ty;
       assert false
 
   let rec array_base_type ty =
@@ -452,7 +554,7 @@ module Make (BasicT : BASIC_TYPES) = struct
   let rec is_generic_type ty =
     match (dynamic_type ty).tdesc with
     | Tarray (d, ty') ->
-      (not (Dimension.is_dimension_const d)) || is_generic_type ty'
+      (not (Dimension.is_const d)) || is_generic_type ty'
     | _ ->
       false
 
@@ -467,7 +569,7 @@ module Make (BasicT : BASIC_TYPES) = struct
     (* Functions are not first order, I don't think the var case needs to be
        considered here *)
     | _ ->
-      Format.eprintf "type %a is not a map@.Unable to split@.@?" print_ty ty;
+      eprintf "type %a is not a map@.Unable to split@.@?" print_ty ty;
       assert false
 
   (** Returns the type corresponding to a type list. *)
@@ -518,132 +620,8 @@ module Make (BasicT : BASIC_TYPES) = struct
   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_const_type : type_expr -> ident -> 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
+include Make (Basic)
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/types.mli b/src/types.mli
new file mode 100644
index 00000000..8653a9dc
--- /dev/null
+++ b/src/types.mli
@@ -0,0 +1,161 @@
+open Utils
+
+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 type S = sig
+  module BasicT : BASIC_TYPES
+
+  type basic_type = BasicT.t
+
+  type t = { mutable tdesc: type_desc; tid: int }
+
+  and type_desc =
+    | Tconst of ident
+    (* type constant *)
+    | Tbasic of basic_type
+    | Tclock of t
+    (* A type expression explicitely tagged as carrying a clock *)
+    | Tarrow of t * t
+    | Ttuple of t list
+    | Tenum of ident list
+    | Tstruct of (ident * t) list
+    | Tarray of Dimension.t * t
+    | Tstatic of Dimension.t * t
+    (* a type carried by a dimension expression *)
+    | Tlink of t
+    (* 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 t * t
+    | Poly_imported_node of ident
+
+  exception Unify of t * t
+
+  exception Error of Location.t * error
+
+  val is_real_type : t -> bool
+
+  val is_int_type : t -> bool
+
+  val is_bool_type : t -> bool
+
+  val is_const_type : t -> ident -> bool
+
+  val is_static_type : t -> bool
+
+  val is_array_type : t -> bool
+
+  val is_dimension_type : t -> bool
+
+  val is_address_type : t -> bool
+
+  val is_generic_type : t -> bool
+
+  val print_ty : Format.formatter -> t -> unit
+
+  val repr : t -> t
+
+  val dynamic_type : t -> t
+
+  val type_desc : t -> type_desc
+
+  val new_var : unit -> t
+
+  val new_univar : unit -> t
+
+  val new_ty : type_desc -> t
+
+  val type_int : type_desc
+
+  val type_real : type_desc
+
+  val type_bool : type_desc
+
+  val type_string : type_desc
+
+  val array_element_type : t -> t
+
+  val type_list_of_type : t -> t list
+
+  val print_node_ty : Format.formatter -> t -> unit
+
+  val get_clock_base_type : t -> t option
+
+  val get_static_value : t -> Dimension.t option
+
+  val is_tuple_type : t -> bool
+
+  val type_of_type_list : t list -> t
+
+  val split_arrow : t -> t * t
+
+  val unclock_type : t -> t
+
+  val bottom : t
+
+  val map_tuple_type : (t -> t) -> t -> t
+
+  val array_base_type : t -> t
+
+  val array_type_dimension : t -> Dimension.t
+
+  val pp_error : Format.formatter -> error -> unit
+
+  val struct_field_type : t -> ident -> t
+
+  val array_type_multi_dimension : t -> Dimension.t list
+end
+
+module Make(BasicT: BASIC_TYPES) : sig
+  include S
+  val print_ty_param: (Format.formatter -> basic_type -> unit) -> Format.formatter -> t -> unit
+end
+with module BasicT = BasicT
+
+include S
diff --git a/src/typing.ml b/src/typing.ml
index 4f5cda9c..762e67e3 100644
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -35,19 +35,20 @@ open Corelang
 module type EXPR_TYPE_HUB = sig
   type type_expr
 
-  val import : Types.Main.type_expr -> type_expr
+  val import : Types.t -> type_expr
 
-  val export : type_expr -> Types.Main.type_expr
+  val export : type_expr -> Types.t
 end
 
 module Make
     (T : Types.S)
-    (Expr_type_hub : EXPR_TYPE_HUB with type type_expr = T.type_expr) =
+    (Expr_type_hub : EXPR_TYPE_HUB with type type_expr = T.t)
+=
 struct
   module TP = Type_predef.Make (T)
   include TP
 
-  let pp_typing_env fmt env = Env.pp_env print_ty fmt env
+  let pp_typing_env fmt env = Env.pp print_ty fmt env
 
   (****************************************************************)
   (* Generic functions: occurs, instantiate and generalize         *)
@@ -219,7 +220,7 @@ struct
         tdef.tydef_desc
       | _ ->
         assert false
-    with Not_found -> raise (Error (Location.dummy_loc, Unbound_type tname))
+    with Not_found -> raise (Error (Location.dummy, Unbound_type tname))
 
   let get_type_definition tname =
     type_coretype (fun _ -> ()) (get_coretype_definition tname)
@@ -252,7 +253,7 @@ struct
       eq_ground t1' t2'
     | Tstatic (e1, t1'), Tstatic (e2, t2') | Tarray (e1, t1'), Tarray (e2, t2')
       ->
-      Dimension.is_eq_dimension e1 e2 && eq_ground t1' t2'
+      Dimension.equal e1 e2 && eq_ground t1' t2'
     | _ ->
       false
 
@@ -312,7 +313,7 @@ struct
         | Tarray (e1, t1'), Tarray (e2, t2') ->
           let eval_const =
             if semi then fun c ->
-              Some (Dimension.mkdim_ident Location.dummy_loc c)
+              Some (Dimension.mkdim_ident Location.dummy c)
             else fun _ -> None
           in
           unif t1' t2';
@@ -757,7 +758,7 @@ struct
             {
               expr_tag = new_tag ();
               expr_desc = Expr_when (expr, x, l);
-              expr_type = Types.Main.new_var ();
+              expr_type = Types.new_var ();
               expr_clock = Clocks.new_var true;
               expr_delay = Delay.new_var ();
               expr_loc = loc;
@@ -1107,16 +1108,15 @@ struct
   let check_typedef_compat header = List.iter check_typedef_top header
 end
 
-include
-  Make
-    (Types.Main)
-    (struct
-      type type_expr = Types.Main.type_expr
+module Expr_type_hub: EXPR_TYPE_HUB with type type_expr = Types.t = struct
+  type type_expr = Types.t
 
-      let import x = x
+  let import x = x
+  let export x = x
+end
+
+include Make(Types)(Expr_type_hub)
 
-      let export x = x
-    end)
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
 (* End: *)
diff --git a/src/typing.mli b/src/typing.mli
new file mode 100644
index 00000000..d0b2a9aa
--- /dev/null
+++ b/src/typing.mli
@@ -0,0 +1,28 @@
+open Lustre_types
+
+val type_const: ?is_annot:bool -> Location.t -> constant -> Types.t
+val type_node: Types.t Env.t -> node_desc -> Location.t -> Types.t Env.t
+
+
+module type EXPR_TYPE_HUB = sig
+  type type_expr
+
+  val import : Types.t -> type_expr
+
+  val export : type_expr -> Types.t
+end
+
+module Make(T: Types.S) (Expr_type_hub: EXPR_TYPE_HUB with type type_expr = T.t) : sig
+  val type_expr: ?is_annot:bool -> T.t Env.t * 'a -> bool -> bool -> expr -> T.t
+  val generalize: T.t -> unit
+end
+
+val try_unify: ?sub:bool -> ?semi:bool -> Types.t -> Types.t -> Location.t -> unit
+
+val type_var_decl_list: 'a -> Types.t Env.t -> var_decl list -> Types.t Env.t
+
+val type_prog: Types.t Env.t -> program_t -> Types.t Env.t
+
+val check_typedef_compat: top_decl list -> unit
+
+val check_env_compat: top_decl list -> Types.t Env.t -> Types.t Env.t -> unit
diff --git a/src/utils/dimension.ml b/src/utils/dimension.ml
index 635cebf3..ceed2413 100644
--- a/src/utils/dimension.ml
+++ b/src/utils/dimension.ml
@@ -11,7 +11,7 @@
 
 open Format
 
-type dim_expr = {
+type t = {
   mutable dim_desc : dim_desc;
   dim_loc : Location.t;
   dim_id : int;
@@ -21,13 +21,13 @@ and dim_desc =
   | Dbool of bool
   | Dint of int
   | Dident of Utils.ident
-  | Dappl of Utils.ident * dim_expr list
-  | Dite of dim_expr * dim_expr * dim_expr
-  | Dlink of dim_expr
+  | Dappl of Utils.ident * t list
+  | Dite of t * t * t
+  | Dlink of t
   | Dvar
   | Dunivar
 
-exception Unify of dim_expr * dim_expr
+exception Unify of t * t
 
 exception InvalidDimension
 
@@ -39,7 +39,7 @@ let mkdim loc dim =
 
 let mkdim_var () =
   incr new_id;
-  { dim_loc = Location.dummy_loc; dim_id = !new_id; dim_desc = Dvar }
+  { dim_loc = Location.dummy; dim_id = !new_id; dim_desc = Dvar }
 
 let mkdim_ident loc id =
   incr new_id;
@@ -61,7 +61,7 @@ let mkdim_ite loc i t e =
   incr new_id;
   { dim_loc = loc; dim_id = !new_id; dim_desc = Dite (i, t, e) }
 
-let rec pp_dimension fmt dim =
+let rec pp fmt dim =
   (*fprintf fmt "<%d>" (Obj.magic dim: int);*)
   match dim.dim_desc with
   | Dident id ->
@@ -71,16 +71,16 @@ let rec pp_dimension fmt dim =
   | Dbool b ->
     fprintf fmt "%B" b
   | Dite (i, t, e) ->
-    fprintf fmt "if %a then %a else %a" pp_dimension i pp_dimension t
-      pp_dimension e
+    fprintf fmt "if %a then %a else %a" pp i pp t
+      pp e
   | Dappl (f, [ arg ]) ->
-    fprintf fmt "(%s%a)" f pp_dimension arg
+    fprintf fmt "(%s%a)" f pp arg
   | Dappl (f, [ arg1; arg2 ]) ->
-    fprintf fmt "(%a%s%a)" pp_dimension arg1 f pp_dimension arg2
+    fprintf fmt "(%a%s%a)" pp arg1 f pp arg2
   | Dappl (_, _) ->
     assert false
   | Dlink dim' ->
-    fprintf fmt "%a" pp_dimension dim'
+    fprintf fmt "%a" pp dim'
   | Dvar ->
     fprintf fmt "_%s" (Utils.name_of_dimension dim.dim_id)
   | Dunivar ->
@@ -105,7 +105,7 @@ let check_access loc d i =
 
 let rec repr dim = match dim.dim_desc with Dlink dim' -> repr dim' | _ -> dim
 
-let rec is_eq_dimension d1 d2 =
+let rec equal d1 d2 =
   let d1 = repr d1 in
   let d2 = repr d2 in
   d1.dim_id = d2.dim_id
@@ -114,9 +114,9 @@ let rec is_eq_dimension d1 d2 =
   | Dappl (f1, args1), Dappl (f2, args2) ->
     f1 = f2
     && List.length args1 = List.length args2
-    && List.for_all2 is_eq_dimension args1 args2
+    && List.for_all2 equal args1 args2
   | Dite (c1, t1, e1), Dite (c2, t2, e2) ->
-    is_eq_dimension c1 c2 && is_eq_dimension t1 t2 && is_eq_dimension e1 e2
+    equal c1 c2 && equal t1 t2 && equal e1 e2
   | Dint i1, Dint i2 ->
     i1 = i2
   | Dbool b1, Dbool b2 ->
@@ -126,17 +126,17 @@ let rec is_eq_dimension d1 d2 =
   | _ ->
     false
 
-let is_dimension_const dim =
+let is_const dim =
   match (repr dim).dim_desc with Dint _ | Dbool _ -> true | _ -> false
 
-let size_const_dimension dim =
+let size_const dim =
   match (repr dim).dim_desc with
   | Dint i ->
     i
   | Dbool b ->
     if b then 1 else 0
   | _ ->
-    Format.eprintf "internal error: size_const_dimension %a@." pp_dimension dim;
+    Format.eprintf "internal error: size_const_dimension %a@." pp dim;
     assert false
 
 let rec is_polymorphic dim =
@@ -176,7 +176,7 @@ let rec factors_constant fs =
 
 let norm_factors fs =
   let k = factors_constant fs in
-  let nk = List.filter (fun d -> not (is_dimension_const d)) fs in
+  let nk = List.filter (fun d -> not (is_const d)) fs in
   k, List.sort compare nk
 
 let rec terms dim =
@@ -229,7 +229,7 @@ let rec eval eval_op eval_const dim =
     | Some val_dim ->
       dim.dim_desc <- Dlink val_dim
     | None ->
-      Format.eprintf "invalid %a@." pp_dimension dim;
+      Format.eprintf "invalid %a@." pp dim;
       raise InvalidDimension)
   | Dite (c, t, e) -> (
     eval eval_op eval_const c;
@@ -242,7 +242,7 @@ let rec eval eval_op eval_const dim =
       ())
   | Dappl (id, args) ->
     List.iter (eval eval_op eval_const) args;
-    if List.for_all is_dimension_const args then
+    if List.for_all is_const args then
       dim.dim_desc <-
         Env.lookup_value eval_op id (List.map (fun d -> (repr d).dim_desc) args)
   | Dlink dim' ->
diff --git a/src/utils/dimension.mli b/src/utils/dimension.mli
new file mode 100644
index 00000000..e99526ad
--- /dev/null
+++ b/src/utils/dimension.mli
@@ -0,0 +1,46 @@
+open Utils
+
+type t = {
+  mutable dim_desc : dim_desc;
+  dim_loc : Location.t;
+  dim_id : int;
+}
+
+and dim_desc =
+  | Dbool of bool
+  | Dint of int
+  | Dident of ident
+  | Dappl of ident * t list
+  | Dite of t * t * t
+  | Dlink of t
+  | Dvar
+  | Dunivar
+
+exception Unify of t * t
+exception InvalidDimension
+
+val mkdim: Location.t -> dim_desc -> t
+val mkdim_ident: Location.t -> ident -> t
+val mkdim_int: Location.t -> int -> t
+val mkdim_bool: Location.t -> bool -> t
+val mkdim_var: unit -> t
+val mkdim_appl: Location.t -> ident -> t list -> t
+val mkdim_ite: Location.t -> t -> t -> t -> t
+
+val pp: Format.formatter -> t -> unit
+
+val is_const: t -> bool
+val is_polymorphic: t -> bool
+val generalize: t -> unit
+val instantiate: (int * t) list ref -> t -> t
+val copy: (int * t) list ref -> t -> t
+val equal: t -> t -> bool
+val eval: (dim_desc list -> dim_desc) Env.t -> (ident -> t option) -> t -> unit
+val unify: ?semi:bool -> t -> t -> unit
+val uneval: ident -> t -> unit
+
+val expr_replace_expr: (ident -> t) -> t -> t
+
+val rename: (ident -> ident) -> (ident -> ident) -> t -> t
+
+val size_const: t -> int
diff --git a/src/utils/env.ml b/src/utils/env.ml
index 8a6c7bca..6e17b948 100644
--- a/src/utils/env.ml
+++ b/src/utils/env.ml
@@ -34,10 +34,10 @@ let overwrite x y =
     (fun _ _old _new -> match _new with Some _ -> _new | _ -> _old)
     x y
 
-let pp_env pp_fun fmt env =
+let pp pp_fun fmt env =
   let l' = IMap.bindings env in
   let pp_fun fmt (id, value) = Format.fprintf fmt "%s |-> %a" id pp_fun value in
-  Format.fprintf fmt "{ @[<v 2>%a@] }" (fprintf_list ~sep:"@," pp_fun) l'
+  Format.(fprintf fmt "{ @[<v 2>%a@] }" (pp_print_list pp_fun) l')
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/utils/env.mli b/src/utils/env.mli
new file mode 100644
index 00000000..5da15267
--- /dev/null
+++ b/src/utils/env.mli
@@ -0,0 +1,12 @@
+open Utils
+
+type 'a t
+
+val initial: 'a t
+val add_value: 'a t -> ident -> 'a -> 'a t
+val lookup_value: 'a t -> ident -> 'a
+val exists_value: 'a t -> ident -> bool
+val iter: 'a t -> (ident -> 'a -> unit) -> unit
+val pp: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+val overwrite: 'a t -> 'a t -> 'a t
+val fold: (ident -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
diff --git a/src/utils/location.ml b/src/utils/location.ml
index 58069a15..b3ed097c 100644
--- a/src/utils/location.ml
+++ b/src/utils/location.ml
@@ -16,7 +16,7 @@ type t = position * position
 
 type filename = string
 
-let dummy_loc = dummy_pos, dummy_pos
+let dummy = dummy_pos, dummy_pos
 
 let set_input, get_input, get_module =
   let input_name : filename ref = ref "__UNINITIALIZED__" in
@@ -33,14 +33,6 @@ let filename_of_loc (s, _) = s.pos_fname
 
 let filename_of_lexbuf lexbuf = lexbuf.lex_start_p.pos_fname
 
-(* let init lexbuf fname =
- *   lexbuf.Lexing.lex_curr_p <- {
- *     Lexing.pos_fname = fname;
- *     Lexing.pos_lnum = 1;
- *     Lexing.pos_bol = 0;
- *     Lexing.pos_cnum = 0;
- *   } *)
-
 let shift_pos pos1 pos2 =
   (* Format.eprintf "Shift pos %s by pos %s@." pos1.Lexing.pos_fname pos2.Lexing.pos_fname;
    * assert (pos1.Lexing.pos_fname = pos2.Lexing.pos_fname); *)
@@ -57,31 +49,10 @@ let shift_pos pos1 pos2 =
          then pos1.pos_cnum + pos2.pos_cnum else pos2.pos_cnum *);
   }
 
-(* let print loc =
- *   let filename = loc.loc_start.pos_fname in
- *   let line = loc.loc_start.pos_lnum in
- *   let start_char =
- *     loc.loc_start.pos_cnum - loc.loc_start.pos_bol
- *   in
- *   let end_char =
- *     loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + start_char
- *   in
- *   let (start_char, end_char) =
- *     if start_char < 0 then (0,1) else (start_char, end_char)
- *   in
- *    print_string ("File \""^filename^"\", line ");
- *   print_int line;
- *   print_string ", characters ";
- *   print_int start_char;
- *   print_string "-";
- *   print_int end_char;
- *   print_string ":";
- *   print_newline () *)
-
 let loc_line (s, _e) = s.pos_lnum
 
-let pp_loc fmt loc =
-  if loc == dummy_loc then () else Format.fprintf fmt "%s" (Lex.range loc)
+let pp fmt loc =
+  if loc = dummy then () else Format.fprintf fmt "%s" (Lex.range loc)
 
 let pp_c_loc fmt (s, _e) =
   let filename = s.pos_fname in
diff --git a/src/utils/location.mli b/src/utils/location.mli
new file mode 100644
index 00000000..c2857c00
--- /dev/null
+++ b/src/utils/location.mli
@@ -0,0 +1,10 @@
+type t = Lexing.position * Lexing.position
+type filename = string
+
+val dummy: t
+val pp: Format.formatter -> t -> unit
+val get_module: unit -> filename
+val curr: Lexing.lexbuf -> t
+val shift: t -> t -> t
+val set_input: filename -> unit
+val filename_of_loc: t -> filename
diff --git a/src/utils/utils.ml b/src/utils/utils.ml
index 5283e7aa..5713cb22 100644
--- a/src/utils/utils.ml
+++ b/src/utils/utils.ml
@@ -52,9 +52,23 @@ module IMap = struct
       m1 m2
 
   let of_list l = List.fold_left (fun m (x, v) -> add x v m) empty l
+
+  let pp ?(comment = "") pp_val fmt m =
+    Format.fprintf fmt "@[<hv 0>@[<hv 2>{ %s" comment;
+    iter (fun key v -> Format.fprintf fmt "@ %s -> %a" key pp_val v) m;
+    Format.fprintf fmt "@]@ }@]"
+end
+
+module ISet = struct
+  include Set.Make (IdentModule)
+
+  let pp fmt t =
+    let open Format in
+    fprintf fmt "@[<hv 0>@[<hv 2>{";
+    iter (fun s -> fprintf fmt "@ %s" s) t;
+    fprintf fmt "@]@ }@]"
 end
 
-module ISet = Set.Make (IdentModule)
 module IdentDepGraph = Imperative.Digraph.ConcreteBidirectional (IdentModule)
 module TopologicalDepGraph = Topological.Make (IdentDepGraph)
 module ComponentsDepGraph = Components.Make (IdentDepGraph)
@@ -407,16 +421,6 @@ let pp_array a pp_fun beg_str end_str sep_str =
     pp_fun a.(n - 1));
   if end_str = "\n" then print_newline () else print_string end_str
 
-let pp_iset fmt t =
-  Format.fprintf fmt "@[<hv 0>@[<hv 2>{";
-  ISet.iter (fun s -> Format.fprintf fmt "@ %s" s) t;
-  Format.fprintf fmt "@]@ }@]"
-
-let pp_imap ?(comment = "") pp_val fmt m =
-  Format.fprintf fmt "@[<hv 0>@[<hv 2>{ %s" comment;
-  IMap.iter (fun key v -> Format.fprintf fmt "@ %s -> %a" key pp_val v) m;
-  Format.fprintf fmt "@]@ }@]"
-
 let pp_hashtbl t pp_fun beg_str end_str sep_str =
   if beg_str = "\n" then print_newline () else print_string beg_str;
   let pp_fun1 k v =
diff --git a/src/utils/utils.mli b/src/utils/utils.mli
new file mode 100644
index 00000000..d738d586
--- /dev/null
+++ b/src/utils/utils.mli
@@ -0,0 +1,93 @@
+type ident = string
+type tag = int
+
+module IMap: sig
+  include Map.S with type key = ident
+  val pp: ?comment:string -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+end
+
+module ISet: sig
+  include Set.S with type elt = ident
+  val pp: Format.formatter -> t -> unit
+end
+
+module Format: sig
+  include module type of Format
+  val pp_print_semicolon: formatter -> unit -> unit
+  val pp_open_vbox0: formatter -> unit -> unit
+  val pp_print_cutcut: formatter -> unit -> unit
+  val pp_print_nothing: formatter -> 'a -> unit
+  val pp_print_list:
+    ?pp_prologue:(formatter -> unit -> unit) ->
+    ?pp_epilogue:(formatter -> unit -> unit) ->
+    ?pp_op:(formatter -> unit -> unit) ->
+    ?pp_cl:(formatter -> unit -> unit) ->
+    ?pp_open_box:(formatter -> unit -> unit) ->
+    ?pp_eol:(formatter -> unit -> unit) ->
+    ?pp_nil:(formatter -> unit -> unit) ->
+    ?pp_sep:(formatter -> unit -> unit) ->
+    (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
+  val pp_comma_list:
+    ?pp_prologue:(formatter -> unit -> unit) ->
+    ?pp_epilogue:(formatter -> unit -> unit) ->
+    ?pp_op:(formatter -> unit -> unit) ->
+    ?pp_cl:(formatter -> unit -> unit) ->
+    ?pp_open_box:(formatter -> unit -> unit) ->
+    ?pp_eol:(formatter -> unit -> unit) ->
+    ?pp_nil:(formatter -> unit -> unit) ->
+    (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
+  val pp_print_parenthesized:
+    ?pp_sep:(formatter -> unit -> unit) ->
+    ?pp_prologue:(formatter -> unit -> unit) ->
+    ?pp_epilogue:(formatter -> unit -> unit) ->
+    ?pp_open_box:(formatter -> unit -> unit) ->
+    ?pp_eol:(formatter -> unit -> unit) ->
+    ?pp_nil:(formatter -> unit -> unit) ->
+    (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
+  val pp_print_bracketed:
+    ?pp_sep:(formatter -> unit -> unit) ->
+    ?pp_prologue:(formatter -> unit -> unit) ->
+    ?pp_epilogue:(formatter -> unit -> unit) ->
+    ?pp_open_box:(formatter -> unit -> unit) ->
+    ?pp_eol:(formatter -> unit -> unit) ->
+    ?pp_nil:(formatter -> unit -> unit) ->
+    (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
+end
+
+module IdentDepGraph: Graph.Sig.I with type V.t = ident
+module TopologicalDepGraph: sig
+  val fold : (ident -> 'a -> 'a) -> IdentDepGraph.t -> 'a -> 'a
+  val iter : (ident -> unit) -> IdentDepGraph.t -> unit
+end
+
+val name_of_dimension: tag -> ident
+
+val name_of_carrier: tag -> ident
+
+val name_of_type: tag -> ident
+
+val name_of_delay: tag -> ident
+
+val reset_names: unit -> unit
+
+val pp_date: Format.formatter -> Unix.tm -> unit
+
+exception TransposeError of int * int
+
+val transpose_list: 'a list list -> 'a list list
+
+val new_tag: unit -> tag
+
+exception DeSome
+
+val desome: 'a option -> 'a
+
+val create_hashtable: int -> ('a * 'b) list -> ('a, 'b) Hashtbl.t
+
+val option_map: ('a -> 'b) -> 'a option -> 'b option
+
+val repeat: int -> ('a -> 'a) -> 'a -> 'a
+
+val add_cons: 'a -> 'a list -> 'a list
+
+val enumerate: int -> int list
diff --git a/src/verifierList.mli b/src/verifierList.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/verifierType.mli b/src/verifierType.mli
new file mode 100644
index 00000000..5bfdeab9
--- /dev/null
+++ b/src/verifierType.mli
@@ -0,0 +1,17 @@
+module type S = sig
+  val name : string
+
+  val activate : unit -> unit
+
+  val is_active : unit -> bool
+
+  val options : (string * Arg.spec * string) list
+
+  val get_normalization_params : unit -> Normalization.param_t
+
+  val run :
+    basename:string ->
+    Lustre_types.program_t ->
+    Machine_code_types.machine_t list ->
+    unit
+end
diff --git a/src/verifiers.mli b/src/verifiers.mli
new file mode 100644
index 00000000..e69de29b
diff --git a/src/version.mli b/src/version.mli
new file mode 100644
index 00000000..e8e24e73
--- /dev/null
+++ b/src/version.mli
@@ -0,0 +1,3 @@
+val number: string
+val codename: string
+val include_path: string
-- 
GitLab