diff --git a/.gitignore b/.gitignore
index 42765851f67e460d370e8baed8a80bb4998717c3..bd07ec66bb53e2b7ab6cb82b7f3316eecb33c041 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,8 @@ grammar.html
 src/generated_parser.ml
 src/config.ml
 **/*.native
+ecomp
 skeleton
 src/.vscode/
 .vscode/
-Makefile.config
\ No newline at end of file
+Makefile.config
diff --git a/Makefile b/Makefile
index 241c2f6c24ef0e5303ebfb827ef7b988e787aaf9..47838aaa427e07b026212bc5925c802c5f333d09 100644
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,33 @@
-all: main.native
+all: ecomp
 
 include opts.mk
 
-.PHONY: main.native
+.PHONY: ecomp
 
 src/config.ml: configure opts.mk
 	./configure ${CONF_OPTS}
 
-main.native: src/config.ml
+.PHONY: alpaga
+alpaga/alpaga:
 	make -C alpaga
+
+src/generated_parser.ml: expr_grammar_action.g alpaga/alpaga
 	./alpaga/alpaga \
 			-g expr_grammar_action.g \
 			-pml src/generated_parser.ml \
 			-t grammar.html
+
+ecomp: src/generated_parser.ml src/config.ml
 	make -C src
-	ln -sf src/main.native main.native
+	ln -sf src/_build/default/main.exe ecomp
 
 clean:
 	make -C alpaga clean
 	rm -f src/generated_parser.ml
 	rm -f grammar.html
 	make -C src clean
-	rm -f main.native
+	rm -f ecomp
 	make -C tests clean
 
-test: main.native
+test: ecomp
 	make -C tests
diff --git a/Sujet.pdf b/Sujet.pdf
index 6e3b066a2f625d74939dbafa9972222d03003dbf..d9bafe17d7526dbda73abd2d6d39e7afb75aec14 100644
Binary files a/Sujet.pdf and b/Sujet.pdf differ
diff --git a/alpaga/.merlin b/alpaga/.merlin
deleted file mode 100644
index 882e9c09fe4d45ededf8a498ac3a85fcbf8c26ec..0000000000000000000000000000000000000000
--- a/alpaga/.merlin
+++ /dev/null
@@ -1,3 +0,0 @@
-S .
-B _build
-PKG batteries
\ No newline at end of file
diff --git a/alpaga/Makefile b/alpaga/Makefile
index ae5b04de755159e85e076276feefcd327da4ec18..caabc9f71a78cf343e81be2a7e14f7a30581e452 100644
--- a/alpaga/Makefile
+++ b/alpaga/Makefile
@@ -1,4 +1,4 @@
-OCB=ocamlbuild -use-ocamlfind -cflag -g
+#OCB=ocamlbuild -use-ocamlfind -cflag -g
 
 SRC=ml_parser_generator.ml \
 	grammar_parser.ml \
@@ -12,11 +12,9 @@ TG = alpaga
 
 all: $(TG)
 
-$(TG): ml_parser_generator.native
-	cp ml_parser_generator.native $(TG)
-
-ml_parser_generator.native: $(SRC)
-	$(OCB) ml_parser_generator.native
+$(TG): $(SRC)
+	dune build ml_parser_generator.exe
+	ln -sf _build/default/ml_parser_generator.exe alpaga
 
 clean:
 	rm -f ml_parser_generator.native $(TG)
diff --git a/alpaga/_tags b/alpaga/_tags
deleted file mode 100644
index 6fea563c5d06918d4cc2d7a963acd8754c9d756b..0000000000000000000000000000000000000000
--- a/alpaga/_tags
+++ /dev/null
@@ -1,3 +0,0 @@
-<.>: include
-true: package(str, batteries)
-true: use_menhir
diff --git a/alpaga/dune b/alpaga/dune
new file mode 100644
index 0000000000000000000000000000000000000000..c1980e29d4a2ce8f8c69cbec0da8baf77ccee6de
--- /dev/null
+++ b/alpaga/dune
@@ -0,0 +1,14 @@
+(menhir
+ (modules grammar_parser_yacc)
+)
+(ocamllex grammar_lexer)
+
+(executable
+ (name ml_parser_generator)
+ (libraries
+   batteries
+   menhirLib
+ )
+ (flags (:standard -warn-error -A -w -27 -w -33 -w -9 -w -39))
+
+)
diff --git a/alpaga/dune-project b/alpaga/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..192d77fdc7853a217a9338cf6209a8cdf00597c5
--- /dev/null
+++ b/alpaga/dune-project
@@ -0,0 +1,2 @@
+(lang dune 2.9)
+(using menhir 2.1)
diff --git a/alpaga/grammar.ml b/alpaga/grammar.ml
index 0032c4d794fcabda226393710b3cecfae08f9c0a..d3a95dd5c5e2e22287287207577dd2645abe50c8 100644
--- a/alpaga/grammar.ml
+++ b/alpaga/grammar.ml
@@ -24,5 +24,6 @@ let dump_grammar oc (toks, nts, rules) =
   Printf.fprintf oc "\nnon-terminals ";
   List.iter (fun n -> Printf.fprintf oc " %s" n) nts;
   Printf.fprintf oc "\nrules\n";
-  List.iter (fun (n,lt,a) -> Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules
+  List.iter (fun (n,lt,_) ->
+      Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules
 
diff --git a/src/.merlin b/src/.merlin
deleted file mode 100644
index 5aca64dac0daf41b44358cea1613e02df7820526..0000000000000000000000000000000000000000
--- a/src/.merlin
+++ /dev/null
@@ -1,11 +0,0 @@
-S .
-B _build
-PKG lwt
-PKG lwt.unix
-PKG logs
-PKG logs.lwt
-PKG batteries
-PKG yojson
-PKG websocket
-PKG websocket-lwt-unix
-PKG menhirLib
\ No newline at end of file
diff --git a/src/Makefile b/src/Makefile
index ea616e9fd16eec28c0af0a909a3e910833e202d5..3c9a73582238f649621436e7687a8a1a838727f1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -9,18 +9,18 @@ ltl_gen.ml ltl_run.ml ltl_debug.ml main.ml options.ml parser.ml prog.ml				\
 regalloc.ml report.ml riscv.ml rtl.ml rtl_print.ml rtl_gen.ml rtl_run.ml			\
 symbols.ml tokenize.ml utils.ml
 
-TG = main.native
+TG = main.exe
 
 PROF:=$(if $(PROF),-ocamlopt ocamloptp,)
 
 all: $(TG)
 
 $(TG): $(SRC)
-	ocamlbuild $(PROF) -cflags  -warn-error,"+a-26" -cflags -w,"-26" -menhir "menhir --unused-tokens" -use-ocamlfind $(TG)
+	dune build $(TG)
+	# ocamlbuild $(PROF) -cflags  -warn-error,"+a-26" -cflags -w,"-26" -menhir "menhir --unused-tokens" -use-ocamlfind $(TG)
 
 test_lexer: archi.ml config.ml e_regexp.ml lexer_generator.ml symbols.ml test_lexer.ml utils.ml
-	ocamlbuild -use-ocamlfind test_lexer.native
-	./test_lexer.native
+	dune exec test_lexer.exe
 	dot -Tsvg /tmp/dfa.dot -o /tmp/dfa.svg
 	dot -Tsvg /tmp/nfa.dot -o /tmp/nfa.svg
 
@@ -28,5 +28,5 @@ config.ml: ../configure ../opts.mk
 	cd .. && ./configure ${CONF_OPTS}
 
 clean:
-	rm -rf _build
-	rm -f config.ml main.native test_lexer.native
+	dune clean
+	rm -f config.ml
diff --git a/src/_tags b/src/_tags
deleted file mode 100644
index 85863b57f6f3a210cf25acdd94cceeb1b6d447d4..0000000000000000000000000000000000000000
--- a/src/_tags
+++ /dev/null
@@ -1,7 +0,0 @@
-true: debug
-true: bin_annot
-<runtime>: -traverse
-<*>: package(lwt lwt.unix logs logs.lwt batteries yojson websocket websocket-lwt-unix menhirLib)
-true: thread
-true: use_menhir, explain, table
-<tykernel>: -traverse
diff --git a/src/archi.ml b/src/archi.ml
index 988790064fc6218be79355941aaed39e8ed720ab..cfaa1b381f91cdf88d6b055240323e8447c393a8 100644
--- a/src/archi.ml
+++ b/src/archi.ml
@@ -1,4 +1,3 @@
-open Config
 
 type archi = A64 | A32
 
diff --git a/src/ast.ml b/src/ast.ml
index 64d50fb94d64f2e7c126921282d64695ab58c8ff..bfd93a8a25c70dd90d9f6504fa19e221ed3bb193 100644
--- a/src/ast.ml
+++ b/src/ast.ml
@@ -1,5 +1,4 @@
 open Batteries
-open BatPrintf
 
 (* Les AST sont des arbres, du type [tree], étiquetés par des [tag].
 
@@ -31,7 +30,7 @@ type tag = Tassign | Tif | Twhile | Tblock | Treturn | Tprint
          | Tlistglobdef
          | Tfundef | Tfunname | Tfunargs | Tfunbody
          | Tassignvar
-         | Targ 
+         | Targ
 
 type tree = | Node of tag * tree list
             | StringLeaf of string
diff --git a/src/cfg.ml b/src/cfg.ml
index 3df451950df479a00cda85835f38178410c72b4b..7c4cb023ce56fa2c68501c5b9369ec311c7996cc 100644
--- a/src/cfg.ml
+++ b/src/cfg.ml
@@ -1,6 +1,5 @@
 open Elang
 open Prog
-open Utils
 open Batteries
 open BatList
 
@@ -51,10 +50,10 @@ let preds cfgfunbody n =
     ) cfgfunbody Set.empty
 
 
-let size_binop b e1 e2 =
+let size_binop _ e1 e2 =
   1 + e1 + e2
 
-let size_unop u e =
+let size_unop _ e =
   1 + e
 
 let rec size_expr (e: expr) : int =
@@ -62,16 +61,16 @@ let rec size_expr (e: expr) : int =
   | Ebinop (b, e1, e2) -> size_binop b (size_expr e1) (size_expr e2)
   | Eunop (u, e) -> size_unop u (size_expr e)
   | Eint _ -> 1
-  | Evar v -> 1
+  | Evar _ -> 1
 
-let rec size_instr (i: cfg_node) : int =
+let size_instr (i: cfg_node) : int =
   match (i : cfg_node) with
-  | Cassign (v, e, s) -> 1 + size_expr e
+  | Cassign (_, e, _) -> 1 + size_expr e
   | Creturn e -> 1 + (size_expr e)
-  | Cprint (e, s) -> 1 + (size_expr e)
-  | Ccmp (e, s1, s2) -> 1 + size_expr e
-  | Cnop s -> 1
+  | Cprint (e, _) -> 1 + (size_expr e)
+  | Ccmp (e, _, _) -> 1 + size_expr e
+  | Cnop _ -> 1
 
 let size_fun f =
-  Hashtbl.fold (fun k v acc -> acc + size_instr v) f 0
+  Hashtbl.fold (fun _ v acc -> acc + size_instr v) f 0
 
diff --git a/src/cfg_constprop.ml b/src/cfg_constprop.ml
index 10ffa8a04e3dbfc7d1c3fc96c22fea114b305563..7309a1a170c5fe60a043427be4d9ffc6ab651cb9 100644
--- a/src/cfg_constprop.ml
+++ b/src/cfg_constprop.ml
@@ -37,8 +37,8 @@ let rec const_prop_expr (e: expr) =
 let constant_propagation_instr (i: cfg_node) : cfg_node =
     i
 
-let constant_propagation_fun ({ cfgfunargs; cfgfunbody; cfgentry } as f: cfg_fun) =
-  let ht = Hashtbl.map (fun n m ->
+let constant_propagation_fun ({ cfgfunbody; _ } as f: cfg_fun) =
+  let ht = Hashtbl.map (fun _ m ->
       constant_propagation_instr m
     ) cfgfunbody in
   { f with cfgfunbody = ht}
diff --git a/src/cfg_dead_assign.ml b/src/cfg_dead_assign.ml
index 8130533fdab83225fe79e4c2dd028ae284f9028d..e35fc4762eb958bb4ec5ad1be98fbbb409a6e39e 100644
--- a/src/cfg_dead_assign.ml
+++ b/src/cfg_dead_assign.ml
@@ -13,7 +13,7 @@ open Options
    function [f]. Cette fonction renvoie un couple [(f',c)] oú [f'] est la
    nouvelle fonction, et [c] est un booléen qui indique si du progrès a été
    fait. *)
-let dead_assign_elimination_fun ({ cfgfunargs; cfgfunbody; cfgentry } as f: cfg_fun) =
+let dead_assign_elimination_fun ({ cfgfunbody; _ } as f: cfg_fun) =
   let changed = ref false in
   let cfgfunbody =
     Hashtbl.map (fun (n: int) (m: cfg_node) ->
diff --git a/src/cfg_gen.ml b/src/cfg_gen.ml
index b20b93392d02bcde3a7e0a8f599991289fd51f54..18509ef62dd1711bdfe41db26dfd56fe3e5676f5 100644
--- a/src/cfg_gen.ml
+++ b/src/cfg_gen.ml
@@ -106,7 +106,7 @@ let cfg_gdef_of_edef gd =
     Gfun f -> cfg_fun_of_efun f >>= fun f -> OK (Gfun f)
 
 let cfg_prog_of_eprog (ep: eprog) : cfg_fun prog res =
-  assoc_map_res (fun fname -> cfg_gdef_of_edef) ep
+  assoc_map_res (fun _ -> cfg_gdef_of_edef) ep
 
 let pass_cfg_gen ep =
   match cfg_prog_of_eprog ep with
diff --git a/src/cfg_liveness.ml b/src/cfg_liveness.ml
index 1fee07ab1b5a52f6a7156862265b25746f3041ce..1671af63478814178261144435ad31d5b85e53d1 100644
--- a/src/cfg_liveness.ml
+++ b/src/cfg_liveness.ml
@@ -1,7 +1,5 @@
 open Batteries
 open Cfg
-open Prog
-open Utils
 
 (* Analyse de vivacité *)
 
diff --git a/src/cfg_print.ml b/src/cfg_print.ml
index 135c810aa53b0a4a040d2d808f7220416f800936..6ec810a6254e741900bea58fd5954da1e5f8062a 100644
--- a/src/cfg_print.ml
+++ b/src/cfg_print.ml
@@ -2,7 +2,6 @@ open Batteries
 open Cfg
 open Elang_print
 open Prog
-open Utils
 
 let rec dump_cfgexpr : expr -> string = function
   | Ebinop(b, e1, e2) -> Format.sprintf "(%s %s %s)" (dump_cfgexpr e1) (dump_binop b) (dump_cfgexpr e2)
@@ -44,7 +43,7 @@ let dump_liveness_state oc ht state =
       flush_all ()
     ) ht
 
-let dump_cfg_fun oc cfgfunname ({ cfgfunargs; cfgfunbody; cfgentry; }: cfg_fun) =
+let dump_cfg_fun oc cfgfunname ({ cfgfunbody; cfgentry; _ }: cfg_fun) =
   Format.fprintf oc "subgraph cluster_%s {\n label=\"%s\";\n" cfgfunname cfgfunname;
   Hashtbl.iter (fun n node ->
       Format.fprintf oc "n_%s_%d [label=\"%a\" xlabel=\"%d\" shape=%s];\n" cfgfunname n dump_cfg_node node n (if n = cfgentry then "rectangle peripheries=2" else "rectangle");
diff --git a/src/dune b/src/dune
new file mode 100644
index 0000000000000000000000000000000000000000..18d7936f4fe6fb1a2ef48f0f1eedc7c6922c26e1
--- /dev/null
+++ b/src/dune
@@ -0,0 +1,19 @@
+(menhir
+ (modules yaccparser)
+ (flags (--unused-tokens))
+  ; unused-tokens
+)
+(ocamllex lexer)
+
+(executable
+ (name main)
+ (libraries
+   batteries
+   yojson
+   lwt
+   websocket
+   websocket-lwt-unix
+   menhirLib
+ )
+ (flags (:standard -warn-error -A -w -27 -w -33 -w -9 -w -39))
+)
diff --git a/src/dune-project b/src/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..192d77fdc7853a217a9338cf6209a8cdf00597c5
--- /dev/null
+++ b/src/dune-project
@@ -0,0 +1,2 @@
+(lang dune 2.9)
+(using menhir 2.1)
diff --git a/src/e_regexp.ml b/src/e_regexp.ml
index 4f6c43f4e9007f42ef117097e9581eb78cb17b1d..bbc5b204ba11e4fcba87a032c342ff699b2719e6 100644
--- a/src/e_regexp.ml
+++ b/src/e_regexp.ml
@@ -66,43 +66,43 @@ let keyword_regexp s = str_regexp (char_list_of_string s)
 (* La liste des expressions régulières permettant d'identifier les tokens du langage E *)
 let list_regexp : (regexp * (string -> token option)) list =
   [
-    (keyword_regexp "while",    fun s -> Some (SYM_WHILE));
-    (keyword_regexp "int", fun s -> Some (SYM_INT));
+    (keyword_regexp "while",    fun _ -> Some (SYM_WHILE));
+    (keyword_regexp "int", fun _ -> Some (SYM_INT));
     (* begin TODO *)
-    (Eps,       fun s -> Some (SYM_VOID));
-    (Eps,       fun s -> Some (SYM_CHAR));
-    (Eps,       fun s -> Some (SYM_IF));
-    (Eps,       fun s -> Some (SYM_ELSE));
-    (Eps,       fun s -> Some (SYM_RETURN));
-    (Eps,       fun s -> Some (SYM_PRINT));
-    (Eps,       fun s -> Some (SYM_STRUCT));
-    (Eps,       fun s -> Some (SYM_POINT));
-    (Eps,       fun s -> Some (SYM_PLUS));
-    (Eps,       fun s -> Some (SYM_MINUS));
-    (Eps,       fun s -> Some (SYM_ASTERISK));
-    (Eps,       fun s -> Some (SYM_DIV));
-    (Eps,       fun s -> Some (SYM_MOD));
-    (Eps,       fun s -> Some (SYM_LBRACE));
-    (Eps,       fun s -> Some (SYM_RBRACE));
-    (Eps,       fun s -> Some (SYM_LBRACKET));
-    (Eps,       fun s -> Some (SYM_RBRACKET));
-    (Eps,       fun s -> Some (SYM_LPARENTHESIS));
-    (Eps,       fun s -> Some (SYM_RPARENTHESIS));
-    (Eps,       fun s -> Some (SYM_SEMICOLON));
-    (Eps,       fun s -> Some (SYM_COMMA));
-    (Eps,       fun s -> Some (SYM_ASSIGN));
-    (Eps,       fun s -> Some (SYM_EQUALITY));
-    (Eps,       fun s -> Some (SYM_NOTEQ));
-    (Eps,       fun s -> Some (SYM_LT));
-    (Eps,       fun s -> Some (SYM_GT));
-    (Eps,       fun s -> Some (SYM_LEQ));
-    (Eps,       fun s -> Some (SYM_GEQ));
+    (Eps,       fun _ -> Some (SYM_VOID));
+    (Eps,       fun _ -> Some (SYM_CHAR));
+    (Eps,       fun _ -> Some (SYM_IF));
+    (Eps,       fun _ -> Some (SYM_ELSE));
+    (Eps,       fun _ -> Some (SYM_RETURN));
+    (Eps,       fun _ -> Some (SYM_PRINT));
+    (Eps,       fun _ -> Some (SYM_STRUCT));
+    (Eps,       fun _ -> Some (SYM_POINT));
+    (Eps,       fun _ -> Some (SYM_PLUS));
+    (Eps,       fun _ -> Some (SYM_MINUS));
+    (Eps,       fun _ -> Some (SYM_ASTERISK));
+    (Eps,       fun _ -> Some (SYM_DIV));
+    (Eps,       fun _ -> Some (SYM_MOD));
+    (Eps,       fun _ -> Some (SYM_LBRACE));
+    (Eps,       fun _ -> Some (SYM_RBRACE));
+    (Eps,       fun _ -> Some (SYM_LBRACKET));
+    (Eps,       fun _ -> Some (SYM_RBRACKET));
+    (Eps,       fun _ -> Some (SYM_LPARENTHESIS));
+    (Eps,       fun _ -> Some (SYM_RPARENTHESIS));
+    (Eps,       fun _ -> Some (SYM_SEMICOLON));
+    (Eps,       fun _ -> Some (SYM_COMMA));
+    (Eps,       fun _ -> Some (SYM_ASSIGN));
+    (Eps,       fun _ -> Some (SYM_EQUALITY));
+    (Eps,       fun _ -> Some (SYM_NOTEQ));
+    (Eps,       fun _ -> Some (SYM_LT));
+    (Eps,       fun _ -> Some (SYM_GT));
+    (Eps,       fun _ -> Some (SYM_LEQ));
+    (Eps,       fun _ -> Some (SYM_GEQ));
     (Eps,       fun s -> Some (SYM_IDENTIFIER s));
     (* end TODO *)
     (Cat(keyword_regexp "//",
          Cat(Star (char_range (List.filter (fun c -> c <> '\n') alphabet)),
              Alt (char_regexp '\n', Eps))),
-     fun s -> None);
+     fun _ -> None);
     (Cat(keyword_regexp "/*",
          Cat(
            Cat (Star (Alt (
@@ -111,7 +111,7 @@ let list_regexp : (regexp * (string -> token option)) list =
                     plus(char_range (List.filter (fun c -> c <> '/' && c <> '*') alphabet)))
              )), Star (char_range ['*'])),
            keyword_regexp "*/")),
-     fun s -> None);
+     fun _ -> None);
     (Cat (char_regexp '\'',
           Cat (char_range (List.filter (fun c -> c <> '\'' && c <> '\\') alphabet),
                char_regexp '\'')),
@@ -141,8 +141,8 @@ let list_regexp : (regexp * (string -> token option)) list =
             ),
                char_regexp '"')),
      fun s -> Some (SYM_STRING (Stdlib.Scanf.unescaped (String.slice ~first:1 ~last:(-1) s))));
-    (char_range (char_list_of_string " \t\n"), fun s -> None);
+    (char_range (char_list_of_string " \t\n"), fun _ -> None);
     (plus digit_regexp, fun s -> Some (SYM_INTEGER (int_of_string s)));
-    (Eps, fun s -> Some (SYM_EOF))
+    (Eps, fun _ -> Some (SYM_EOF))
   ]
 
diff --git a/src/elang.ml b/src/elang.ml
index 76c786546e12f93c3c61e3b1239c2a199b830682..72b8e18b5c4a94b0226063a502ed274af1822d59 100644
--- a/src/elang.ml
+++ b/src/elang.ml
@@ -1,7 +1,4 @@
-open Ast
-open Batteries
 open Prog
-open Utils
 
 type binop = Eadd | Emul | Emod | Exor | Ediv | Esub (* binary operations *)
            | Eclt | Ecle | Ecgt | Ecge | Eceq | Ecne (* comparisons *)
diff --git a/src/elang_run.ml b/src/elang_run.ml
index f955cd1f2913dc47d20389d585da570bc124145f..494b2c6ac0da84d327a4e1016b7da8f57b3ae57e 100644
--- a/src/elang_run.ml
+++ b/src/elang_run.ml
@@ -1,10 +1,7 @@
 open Elang
 open Batteries
-open BatList
 open Prog
 open Utils
-open Builtins
-open Utils
 
 let binop_bool_to_int f x y = if f x y then 1 else 0
 
@@ -88,5 +85,5 @@ let eval_eprog oc (ep: eprog) (memsize: int) (params: int list)
   (* ne garde que le nombre nécessaire de paramètres pour la fonction "main". *)
   let n = List.length f.funargs in
   let params = take n params in
-  eval_efun oc st f "main" params >>= fun (v, st) ->
+  eval_efun oc st f "main" params >>= fun (v, _) ->
   OK v
diff --git a/src/ltl_debug.ml b/src/ltl_debug.ml
index b3d870aa9f3446f21bb59a5411bf4b53bff0d6f5..6e2d7753b21d0161f75ad66b400dad93b9a118b3 100644
--- a/src/ltl_debug.ml
+++ b/src/ltl_debug.ml
@@ -214,11 +214,11 @@ let debug_ltl_prog progname lp memsize params : unit=
   let st = ref (init_state memsize lp params) in
   let state = ref (None) in
   let breaks = ref [] in
-  let ctx = Conduit_lwt_unix.default_ctx in
+  let ctx = Lazy.force Conduit_lwt_unix.default_ctx in
   let uri = "http://localhost:8080" in
   let (pstop, rstop) = Lwt.task () in
   let server () =
-    Resolver_lwt.resolve_uri (Uri.of_string uri) Resolver_lwt_unix.system >>= fun endp ->
+    Resolver_lwt.resolve_uri ~uri:(Uri.of_string uri) Resolver_lwt_unix.system >>= fun endp ->
     Conduit_lwt_unix.endp_to_server ~ctx endp >>= fun server ->
     Websocket_lwt_unix.establish_server
       ~ctx ~mode:server
diff --git a/src/ltl_gen.ml b/src/ltl_gen.ml
index 609470626ef64f1258b4e29bae8775798135e8a3..aa6a9fa16cc866bdcb76848577ada490f3b5ae22 100644
--- a/src/ltl_gen.ml
+++ b/src/ltl_gen.ml
@@ -325,7 +325,7 @@ let ltl_instrs_of_linear_instr fname live_out allocation
   | Rlabel l -> OK [LLabel (Format.sprintf "%s_%d" fname l)]
   in
   res >>= fun l ->
-  OK (LComment (Format.asprintf "#<span style=\"background: pink;\"><b>Linear instr</b>: %a #</span>" (Rtl_print.dump_rtl_instr fname (None, None)) ins)::l)
+  OK (LComment (Format.asprintf "#<span style=\"background: pink;\"><b>Linear instr</b>: %a #</span>" (Rtl_print.dump_rtl_instr fname (None, None) ~endl:"") ins)::l)
 
 (** Retrieves the location of the n-th argument (in the callee). The first 8 are
    passed in a0-a7, the next are passed on the stack. *)
diff --git a/src/main.ml b/src/main.ml
index 7df1d41e4df078f4dcbc5e53782f7e805b497dbc..92b967f912e7519179fbca97c174b70313980d05 100644
--- a/src/main.ml
+++ b/src/main.ml
@@ -165,7 +165,7 @@ let _ =
   | Some input ->
     add_to_report "Source" "Source" (Code (file_contents input));
 
-    match Filename.chop_suffix_opt ".e" input with
+    match Filename.chop_suffix_opt ~suffix:".e" input with
       None -> failwith
                 (Format.sprintf "File (%s) should end in .e" input)
     | Some basename ->
diff --git a/src/report.ml b/src/report.ml
index ba312d99e4715967ff4e4c237b5494ee28f6df3f..82fddb4da1531c5e29b7007a980d5cf00b188de7 100644
--- a/src/report.ml
+++ b/src/report.ml
@@ -25,18 +25,59 @@ let add_to_report id title content =
 
 let make_report filename report () =
   let html = open_out (filename ^ ".html") in
-  Printf.fprintf html "<ul id=\"top\">";
+  Printf.fprintf html "\
+<html>\n\
+    <head>\n\
+            <link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">\n\
+    <script src=\"https://kit.fontawesome.com/1f5d81749b.js\" crossorigin=\"anonymous\"></script>\n\
+    <style type=\"text/css\">\n\
+    a.anchor {\n\
+      display: block; \
+      position: relative; \
+      left: -250px; \
+    visibility: hidden;\
+    }\n\
+    </style>\n\
+    </head>\n\
+    <body>\n\
+";
+  Printf.fprintf html "<div \
+                       class=\"w3-container w3-cell\" \
+                       style=\"position: fixed; z-index: 1; top: 0; bottom: 0; width: 250px; overflow-y: scroll;\"\
+                       >\n  <ul class=\"w3-ul\">\n";
+  let t = Unix.time () in
+  let tm = Unix.localtime t in
+  let open Unix in
+  Printf.fprintf html "<li>%02d/%02d/%04d - %02dh%02d</li>"
+    tm.tm_mday
+    (tm.tm_mon + 1)
+    (tm.tm_year + 1900)
+    tm.tm_hour
+    tm.tm_min
+  ;
+  Printf.fprintf html "  <li><a href=\"../results.html\"><i class=\"fa fa-home\"></i> Results</a></li>\n";
   List.iter
-    (fun { sect_id; sect_title  } ->
-       Printf.fprintf html "<li><a href=\"#%s\">%s</a></li>\n" sect_id sect_title
+    (fun { sect_id; sect_title; _ } ->
+       Printf.fprintf html "  <li><a href=\"#%s\">%s</a></li>\n" sect_id sect_title
     )
     !report;
-  Printf.fprintf html "</ul>";
+  Printf.fprintf html "</ul></div><div \
+                       class=\"w3-container w3-cell-row\" \
+                       style=\"margin-left: 250px;\"\
+                       ><a class=\"anchor\" id=\"top\"></a>";
   List.iter
     (fun { sect_id; sect_title; sect_content } ->
-       Printf.fprintf html "<fieldset><h3 id=\"%s\"><a href=\"#top\">&uarr;</a> %s</h3>%a</fieldset>\n" sect_id sect_title print_html sect_content
+       Printf.fprintf html "<fieldset>\n\
+                            <a class=\"anchor\" id=\"%s\"></a>\n\
+                            <h3><a href=\"#top\">&uarr;</a> %s</h3>\n\
+                            %a\n\
+                            </fieldset>\n" sect_id sect_title print_html sect_content
     )
     !report;
+  Printf.fprintf html "\
+</div>\n\
+</body>\n\
+</html>";
   close_out html;
   ()
 
@@ -109,7 +150,7 @@ let timeout (f: 'a -> 'b res) (arg: 'a) (time: float) : ('b * string) res =
         Marshal.to_channel oc (Error (Printf.sprintf "Timeout after %f seconds." time)) [];
         close_out oc;
         exit 0
-      | pid1 -> let ic = Unix.in_channel_of_descr pipe_r in
+      | _ -> let ic = Unix.in_channel_of_descr pipe_r in
         let result = Marshal.from_channel ic in
         result ))
 
@@ -146,7 +187,6 @@ let run step flag eval p =
 
 
 let json_output_string () =
-  let open Yojson in
   let jstring_of_ostring o =
     match o with
     | None -> `Null
diff --git a/src/rtl.ml b/src/rtl.ml
index 3ce33fdec0214095ec8ced78b74b5e8e5c76b275..ab703a052a576fcb000cc3eb1ed68a08653d225b 100644
--- a/src/rtl.ml
+++ b/src/rtl.ml
@@ -1,9 +1,6 @@
 open Batteries
-open BatList
 open Elang
 open Cfg
-open Utils
-open Prog
 
 type reg = int
 
diff --git a/src/rtl_print.ml b/src/rtl_print.ml
index c8ed813944d2722f5266a043b1af819e2d321860..f0b473438d9927b2ae15de2daf7975c48bb44a20 100644
--- a/src/rtl_print.ml
+++ b/src/rtl_print.ml
@@ -17,7 +17,7 @@ let print_cmpop (r: rtl_cmp) =
   | Rceq -> "=="
   | Rcne -> "!=")
 
-let dump_rtl_instr name (live_in, live_out) oc (i: rtl_instr) =
+let dump_rtl_instr name (live_in, live_out) ?(endl="\n") oc (i: rtl_instr) =
   let print_node s = Format.sprintf "%s_%d" name s in
 
   let dump_liveness live where =
@@ -42,7 +42,7 @@ let dump_rtl_instr name (live_in, live_out) oc (i: rtl_instr) =
   | Rprint r -> Format.fprintf oc "print %s" (print_reg r)
   | Rlabel n -> Format.fprintf oc "%s_%d:" name n
   end;
-  Format.fprintf oc "\n";
+  Format.fprintf oc "%s" endl;
   dump_liveness live_out "after"
 
 let dump_rtl_node name lives =
@@ -52,6 +52,7 @@ let dump_rtl_node name lives =
            None -> (None, None)
          | Some (lin, lout) ->
            Hashtbl.find_option lin i, Hashtbl.find_option lout i)
+        ~endl:"\n"
     ) "" "" ""
 
 let dump_rtl_fun oc rtlfunname ({ rtlfunargs; rtlfunbody; rtlfunentry }: rtl_fun) =
diff --git a/src/symbols.ml b/src/symbols.ml
index 8659b7511b8b4b9b7c2e2817685332e523cab7e7..71760ef8380d4e4fefc2f934565fab43c68fe9b4 100644
--- a/src/symbols.ml
+++ b/src/symbols.ml
@@ -1,6 +1,4 @@
-open BatPrintf
 open Batteries
-open Utils
 
 let string_of_position pos =
   let open Lexing in
diff --git a/src/utils.ml b/src/utils.ml
index 48ad33f9c0eef6eccb7c40fa7f7d3a42e4d5da32..35479bfb29f2ae40c4c2c6aba8a764010feaa3f9 100644
--- a/src/utils.ml
+++ b/src/utils.ml
@@ -1,5 +1,4 @@
 open Batteries
-open BatPrintf
 open BatBuffer
 open BatList
 
@@ -131,18 +130,18 @@ module Mem : sig
   val write_log : t -> unit -> (int * int) list
 end = struct
   type t = int array * int list ref * (int * int) list ref
-  let write_bytes (m,rl,wl) addr bytes =
+  let write_bytes (m,_,wl) addr bytes =
     write_mem_bytes m addr bytes >>= fun w ->
     wl := w @ !wl; OK ()
-  let write_char (m,rl,wl) addr c =
+  let write_char (m,_,wl) addr c =
     write_mem_char m addr c >>= fun w -> wl := w @ !wl; OK ()
-  let read_bytes (m,rl,wl) addr len =
+  let read_bytes (m,rl,_) addr len =
     read_mem_bytes m addr len >>= fun (vl,addrl) ->
     rl := addrl @ !rl ; OK vl
-  let read_bytes_as_int (m,rl,wl) addr len =
+  let read_bytes_as_int (m,rl,_) addr len =
     read_mem_bytes_as_int m addr len >>= fun (v,addrl) ->
     rl := addrl @ !rl; OK v
-  let read_char (m,rl,wl) addr =
+  let read_char (m,rl,_) addr =
     read_mem_char m addr >>= fun (v,addrl) ->
     rl := addrl @ !rl; OK v
   let init n = Array.init n (fun _ -> 0), ref [], ref []
@@ -154,7 +153,7 @@ let assoc_opti k l =
   let rec aux l n =
     match l with
     | [] -> None
-    | (a,v)::l when a = k -> Some (n, v)
+    | (a,v)::_ when a = k -> Some (n, v)
     | _::l -> aux l (n+1)
   in
   aux l 0
@@ -169,7 +168,7 @@ let assoc_map_res f l =
       OK (acc@[(k,v)])
     ) (OK []) l
 
-let rec assoc_split fl fr l =
+let assoc_split fl fr l =
   let rec aux l (accl, accr) =
   match l with
   | [] -> (accl, accr)
@@ -339,7 +338,7 @@ let file_contents file =
       try
         let line = input_line ic in  (* read line from in_channel and discard \n *)
         aux (s ^ line ^ "\n") ()   (* close the input channel *)
-      with e ->                      (* some unexpected exception occurs *)
+      with _ ->                      (* some unexpected exception occurs *)
         close_in_noerr ic;           (* emergency closing *)
         s in
     aux "" ()
diff --git a/tests/Makefile b/tests/Makefile
index 78c3657f7a434bd91dd0b8d0d4c4a55edfd59f09..7f5a992327ddebee63e223a3f3eda7070950bfbf 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -6,13 +6,13 @@ FILES := $(if $(DIR),$(DIR),basic/*.e)
 OPTS := $(if $(OPTS), $(OPTS),)
 
 .PHONY: all
-all: ../main.native
+all: ../ecomp
 	./test.py -f $(FILES) $(OPTS)
 
-expect: ../main.native
+expect: ../ecomp
 	OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 1 2 3
 	OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 14 12 3 8 12
-	for f in $(FILES); do ../main.native -f $$f -show-tokens $$f.expect_lexer; done
+	for f in $(FILES); do ../ecomp -f $$f -show-tokens $$f.expect_lexer; done
 
 
 clean:
diff --git a/tests/basic/whileret.e b/tests/basic/whileret.e
deleted file mode 100644
index 921facb0703457a4ac60fde806d771d080b13175..0000000000000000000000000000000000000000
--- a/tests/basic/whileret.e
+++ /dev/null
@@ -1,9 +0,0 @@
-main(x){
-  while(x > 0){
-    if (x == 3){
-      return 12;
-    }
-    x = x - 1;
-  }
-  return -3;
-}
diff --git a/tests/basic/whileret.e.expect_14_12_3_8_12 b/tests/basic/whileret.e.expect_14_12_3_8_12
deleted file mode 100644
index bcf7b802b7bc81daf4f5967753206a451b8eac6e..0000000000000000000000000000000000000000
--- a/tests/basic/whileret.e.expect_14_12_3_8_12
+++ /dev/null
@@ -1 +0,0 @@
-{"output": "", "error": null, "retval": 12}
\ No newline at end of file
diff --git a/tests/basic/whileret.e.expect_1_2_3 b/tests/basic/whileret.e.expect_1_2_3
deleted file mode 100644
index e50078bef0dc9408205eb44eb97394dfaff5447d..0000000000000000000000000000000000000000
--- a/tests/basic/whileret.e.expect_1_2_3
+++ /dev/null
@@ -1 +0,0 @@
-{"output": "", "error": null, "retval": -3}
\ No newline at end of file
diff --git a/tests/basic/whileret.e.expect_lexer b/tests/basic/whileret.e.expect_lexer
deleted file mode 100644
index 8f900ffcd7084813acfd539f3115ca7a34433e04..0000000000000000000000000000000000000000
--- a/tests/basic/whileret.e.expect_lexer
+++ /dev/null
@@ -1,36 +0,0 @@
-SYM_IDENTIFIER(main)
-SYM_LPARENTHESIS
-SYM_IDENTIFIER(x)
-SYM_RPARENTHESIS
-SYM_LBRACE
-SYM_WHILE
-SYM_LPARENTHESIS
-SYM_IDENTIFIER(x)
-SYM_GT
-SYM_INTEGER(0)
-SYM_RPARENTHESIS
-SYM_LBRACE
-SYM_IF
-SYM_LPARENTHESIS
-SYM_IDENTIFIER(x)
-SYM_EQUALITY
-SYM_INTEGER(3)
-SYM_RPARENTHESIS
-SYM_LBRACE
-SYM_RETURN
-SYM_INTEGER(12)
-SYM_SEMICOLON
-SYM_RBRACE
-SYM_IDENTIFIER(x)
-SYM_ASSIGN
-SYM_IDENTIFIER(x)
-SYM_MINUS
-SYM_INTEGER(1)
-SYM_SEMICOLON
-SYM_RBRACE
-SYM_RETURN
-SYM_MINUS
-SYM_INTEGER(3)
-SYM_SEMICOLON
-SYM_RBRACE
-SYM_EOF
diff --git a/tests/test.py b/tests/test.py
index 06f26656aafd5a4a2910fb651593d6fa6bf913e9..91bf090cca70a4e8209ab6691bd7356f71552d46 100755
--- a/tests/test.py
+++ b/tests/test.py
@@ -1,100 +1,57 @@
 #!/usr/bin/python3
-import argparse, glob
+"""Test orchestration for ecomp"""
+import argparse
+import glob
 from threading import Thread
-import subprocess
 import json
-from subprocess import *
+from subprocess import Popen, PIPE
 import signal
 import sys
 import time
 import textwrap
 import difflib
-
-parser = argparse.ArgumentParser()
-parser.add_argument("-f", "--file",
-                    help="files to compile",
-                    default=glob.glob("*.e"),
-                    nargs='+')
-parser.add_argument("-p", "--passes",
-                    help="passes to execute",
-                    nargs='+',
-                    default=["e-run",
-                             "cfg-run",
-                             "cfg-run-after-cp",
-                             "cfg-run-after-dae",
-                             "cfg-run-after-ne",
-                             "rtl-run",
-                             "linear-run",
-                             "linear-run-after-dse",
-                             "ltl-run",
-                             "riscv-run"])
-parser.add_argument("--args",
-                    help="args for programs",
-                    nargs='+',
-                    default=["14","12","3","8","12"])
-parser.add_argument("--html", help="Output HTML file",
-                    default="results.html")
-parser.add_argument("-d", "--dry-run", help="Dry-run. Don't actually compile anything",
-                    action="store_true")
-parser.add_argument("-v", "--verbose", help="Verbosity level",
-                    action="count", default=0)
-parser.add_argument("--make-expect", help="Make .expect files for each test",
-                    action="store_true")
-args,unknown_args = parser.parse_known_args()
-
-# show options
-if(args.verbose >= 1):
-    print("args.file=" + str(args.file))
-    print("args.passes=" + str(args.passes))
-    print("args.args=" + str(args.args))
-    print("args.html=" + str(args.html))
-    print("args.dry_run=" + str(args.dry_run))
-    print("args.verbose=" + str(args.verbose))
-
-# construct the set of commands to be launched, one per file
-cmds = []
-for f in args.file:
-    cmd = "../main.native -json {}.json -f {} {} {} -- {}".format(f, f,
-                                                 " ".join(map(lambda s : "-"+s, args.passes)),
-                                                       " ".join(unknown_args),
-                                                 " ".join(args.args)
-    )
-    cmds.append((f,cmd))
-
-# dyr_run : simply show the commands but don't execute them
-if args.dry_run:
-    for (f,cmd) in cmds:
-        print(cmd)
-    exit()
-
-# The list of threads that will be launched
-threads = []
+from typing import List
+import datetime
 
 # The displayer thread shows what commands are still running
 class Displayer(Thread):
-    def __init__(self):
+    """A Displayer thread"""
+
+    def __init__(self, threads):
         Thread.__init__(self)
+        self.threads = threads
 
     def run(self):
         width = 120
-        l = [x for x in threads if x.running]
-        while len(l):
-            s = "{} threads running ".format(len(l))
-            thrs = str(list(map(lambda x: x.f, l)))[:(width-len(s))]
-            print("\r{}({}).{}".format(s, thrs, " "*(width-len(thrs) - len(s))), end="")
+        l_running = [x for x in self.threads if x.running]
+        while len(l_running) > 0:
+            s_running = "{} threads running ".format(len(l_running))
+            thrs = str(list(map(lambda x: x.filename,
+                                l_running)))[:(width - len(s_running))]
+            print("\r{}({}).{}".format(
+                s_running, thrs, " " * (width - len(thrs) - len(s_running))),
+                  end="")
             time.sleep(1)
-            l = [x for x in threads if x.running]
+            l_running = [x for x in self.threads if x.running]
         print()
 
-# The number of columns in the HTML table
-numcols = len(args.passes) + 1 # 1 colonne pour le lexer
+
+
 
 def display_verbatim(body):
-    return '\n'.join(['\n'.join(textwrap.wrap(line, 90,
-                                              break_long_words=False, replace_whitespace=False))
-                      for line in body.splitlines() if line.strip() != ''])
+    "Show verbatim contents"
+    return '\n'.join([
+        '\n'.join(
+            textwrap.wrap(line,
+                          90,
+                          break_long_words=False,
+                          replace_whitespace=False))
+        for line in body.splitlines() if line.strip() != ''
+    ])
+
 
 def make_td(td):
+    "Create a TD HTML tag"
     if isinstance(td, list):
         text = td[0]
         opts = " ".join(td[1:])
@@ -102,16 +59,18 @@ def make_td(td):
         text = str(td)
         opts = ""
 
-    return "<td {}>{}</td>".format(opts,text)
+    return "<td {}>{}</td>".format(opts, text)
 
-def make_table_row(tds):
-    return "<tr>\n" + "".join(map(make_td,tds)) + "</tr>\n"
+icon_ok = "<i class='fa fa-check' style='color: green;'></i>"
+icon_warn = "<i class='fa fa-exclamation-circle' style='color: orange;'></i>"
+icon_ko = "<i class='fa fa-times-circle' style='color:red;'></i>"
 
 # CommandExecutor run a command [cmd] and operates on file [f]
 class CommandExecutor(Thread):
-    def __init__(self, f, cmd):
+    """Command Executor"""
+    def __init__(self, filename, cmd, args, make_expect, numcols):
         Thread.__init__(self)
-        self.f = f
+        self.filename = filename
         self.cmd = cmd
         self.s = ""
         self.running = True
@@ -119,210 +78,358 @@ class CommandExecutor(Thread):
         self.stderr = ""
         self.lastcorrectstep = -1
         self.proc = None
+        self.args = args
+        self.make_expect = make_expect
+        self.numcols = numcols
 
     # run cmd and get stdout and stderr in dict
-    def run_capture_output_interruptible(self,cmd):
-        process = Popen(cmd, stdout=PIPE, stderr=PIPE)
-        self.proc = process
+    def run_capture_output_interruptible(self, cmd):
+        self.proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
         try:
-            stdout, stderr = process.communicate()
-            retcode = process.poll()
-            return {'stdout' : stdout, 'stderr': stderr}
+            self.stdout, self.stderr = self.proc.communicate()
+            self.proc.poll()
+            self.stdout = self.stdout.decode('utf8')
+            self.stderr = self.stderr.decode('utf8')
         except:
-            return {'stdout' : b"[]", 'stderr': ""}
+            self.stdout = (b"[]").decode('utf8')
+            self.stderr = "".decode('utf8')
 
     def stop(self):
+        """Stop the thread"""
         if self.proc:
             self.proc.kill()
 
-    def run(self):
-        c = self.cmd.split(" ")
-        process = self.run_capture_output_interruptible(c)
-        self.stdout = process['stdout'].decode('utf8')
-        self.stderr = process['stderr'].decode('utf8')
-        json_file_name = self.f + ".json"
-        j = []
+    def get_test_results(self, json_file_name):
+        "Get test results, handle errors"
         try:
             with open(json_file_name, 'r') as jsonfile:
                 try:
-                    j = json.load(jsonfile)
+                    return json.load(jsonfile)
                 except:
-                    j.append({'retval':-1,
-                              'output': display_verbatim(self.stdout),
-                              'error': display_verbatim(self.stderr)})
+                    return [{
+                        'retval': -1,
+                        'output': display_verbatim(self.stdout),
+                        'error': display_verbatim(self.stderr)
+                    }]
         except:
-            j.append({'retval':-1,
-                      'output': display_verbatim(self.stdout),
-                      'error': "No file {} generated...".format(json_file_name)})
-        old_ret = None
-        old_out = None
-        old_err = None
+            return [{
+                'retval': -1,
+                'output': display_verbatim(self.stdout),
+                'error': "No file {} generated...".format(json_file_name)
+            }]
+
+    @staticmethod
+    def register_expect(expect_file_name, out, err, ret):
+        "Creates a .expect file"
+        with open(expect_file_name, 'w') as expectfile:
+            json.dump(
+                {
+                    'output': out,
+                    'error': err,
+                    'retval': ret
+                }, expectfile)
+
+    @staticmethod
+    def check_expect(expect_file_name, out, err, ret):
+        "Checks a result wrt an expect file"
+        try:
+            with open(expect_file_name, 'r') as expectfile:
+                j = json.load(expectfile)
+                return j['retval'] == ret and \
+                    j['output'] == out and \
+                    j['error'] == err
+        except:
+            return None
+     
+
+    def run(self):
+        """Actually run the test"""
+        self.run_capture_output_interruptible(self.cmd.split(" "))
+        json_file_name = self.filename + ".json"
+        j = self.get_test_results(json_file_name)
         self.s = ""
         curcol = 0
-        numrunstep = 0
-        for i, r in enumerate(j, start=0):
+        first_runstep = True
+        for _, r in enumerate(j, start=0):
             if "runstep" in r:
-                expect_file_name = self.f + ".expect_" + "_".join(args.args)
-                if numrunstep == 0:
-                    if args.make_expect:
-                        with open(expect_file_name, 'w') as expectfile:
-                            json.dump({ 'output' : r['output'],
-                                        'error' : r['error'],
-                                        'retval': r['retval']}, expectfile)
-                numrunstep = numrunstep + 1
-                if old_ret == None:
-                    old_ret = r['retval']
-                if old_out == None: old_out = r['output']
-                if old_err == None: old_err = r['error']
+                expect_file_name = self.filename + ".expect_" + "_".join(self.args)
+                if first_runstep and self.make_expect:
+                    self.register_expect(expect_file_name, r['output'], r['error'], r['retval'])
+                first_runstep = False
                 cls = "good"
-                try:
-                    with open(expect_file_name, 'r') as expectfile:
-                        j = json.load(expectfile)
-                        if j['retval'] == r['retval'] and j['output'] == r['output'] and j['error'] == r['error']:
-                            cls = "good"
-                        else:
-                            cls = "bad"
-                except:
+                test_ok = self.check_expect(expect_file_name, r['output'], r['error'], r['retval'])
+                if test_ok is None:
                     cls = ""
+                else:
+                    cls = "good" if test_ok else "bad"
                 if cls == "good":
                     self.lastcorrectstep = curcol
-                self.s += make_td(["Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.<br>".
-                                   format(r['retval'], r['output'],
-                                          "Error: <pre>"+r['error']+"</pre>" if r['error'] != None else "",
-                                          r['time']),
-                                   "class=\"{}\"".format(cls)])
-                curcol+=1
+                err_str = "Error: <pre>" + r['error'] + "</pre>" if r['error'] is not None else ""
+                self.s += make_td([
+                    "{}<div name='{}' style='display:none;'>Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.</div>"
+                    .format(
+                        icon_ok if cls == 'good' else icon_ko,
+                        self.filename,
+                        r['retval'],
+                        r['output'],
+                        err_str,
+                        r['time']),
+                    "class=\"{}\"".format(cls)
+                ]) + "\n"
+                curcol += 1
             elif "compstep" in r:
 
                 compstep_td = ""
                 err = r['error']
-                if err != None:
-                    compstep_td="""
-                    <td class="bad" style="text-align: left;" colspan="{}">{} error:<br><pre>{}</pre></td>
-                    """.format( numcols - curcol, r['compstep'],err)
-                    self.s += compstep_td
-                    break
+                if err is not None:
+                    compstep_td = """
+                    <td class="bad" style="text-align: left;" colspan="{}">{}<div name='{}' style='display:none'>{} error:<br><pre>{}</pre></div></td>
+                    """.format(self.numcols - curcol,
+                               icon_ko,
+                               self.filename,
+                               r['compstep'], err)
 
                 elif r["compstep"] == "Lexing":
-                    expect_lex_file_name = self.f + ".expect_lexer"
-                    out_lex_file_name = self.f[:-2] + ".lex"
+                    expect_lex_file_name = self.filename + ".expect_lexer"
+                    out_lex_file_name = self.filename[:-2] + ".lex"
                     try:
-                        with open(expect_lex_file_name, "r") as expect_lex_file, open(out_lex_file_name, "r") as out_lex_file:
+                        with open(expect_lex_file_name, "r") as expect_lex_file, \
+                             open(out_lex_file_name, "r") as out_lex_file:
                             expected_tokens = expect_lex_file.readlines()
                             out_tokens = out_lex_file.readlines()
-                            diff = difflib.unified_diff(expected_tokens, out_tokens,
-                                                        fromfile=expect_lex_file_name,
-                                                        tofile=out_lex_file_name)
+                            diff = difflib.unified_diff(
+                                expected_tokens,
+                                out_tokens,
+                                fromfile=expect_lex_file_name,
+                                tofile=out_lex_file_name)
                             diff = list(diff)
                             if diff == []:
-                                compstep_td = "<td class=\"good\">OK</td>"
+                                compstep_td = "<td class=\"good\">{}</td>".format(icon_ok)
                             else:
-                                compstep_td = "<td class=\"warn\" style=\"text-align: left;\" >{} not-what-expected:<br><pre>".format(r['compstep'])
-                                for line in diff:
-                                    compstep_td += line
-                                compstep_td += "{}</pre></td>"
+                                compstep_td = "<td class=\"warn\" style=\"text-align: left;\" >{}<div name='{}'>Lexing not-what-expected:<br><pre>{}</pre></div></td>".format(icon_warn, self.filename, "".join(diff))
                     except:
                         compstep_td = "<td>No .expect_lexer file</td>"
 
-
-                self.s += compstep_td
+                self.s += compstep_td + "\n"
             else:
                 err = r['error']
-                if err != None:
-                    self.s +="""
+                if err is not None:
+                    self.s += """
                     <td class="bad" style="text-align: left;" colspan="{}">error:<br><pre>{}</pre></td>
-                    """.format( numcols - curcol, err)
+                    """.format(self.numcols - curcol, err) + "\n"
                 else:
-                    self.s +="""
+                    self.s += """
                     <td class="bad" colspan="{}">error:<br><pre>{}</pre></td>
-                    """.format( numcols - curcol, r)
-
-        self.s = """<tr><td class="rowname"><a href="{}.html">{}</a></td>{}</tr>""".format(self.f,self.f,self.s)
-        self.running = False
-
+                    """.format(self.numcols - curcol, r) + "\n"
 
-def interrupt_handler(sig, frame):
-    print('You pressed Ctrl+C!')
-    for t in threads:
-        t.stop()
-
-signal.signal(signal.SIGINT, interrupt_handler)
-
-
-for (f,cmd) in cmds:
-    t = CommandExecutor(f, cmd)
-    threads.append(t)
-    t.start()
-
-
-d = Displayer()
-d.start()
-
-
-for t in threads:
-    t.join()
-
-d.join()
-print ("All threads terminated!")
-
-res_html = open(args.html, "w")
-res_html.write("""
-<style type="text/css">
-
-table , table th, table td , table tr{
-    border: 1px solid black;
-    border-collapse: collapse;
-    text-align: center;
-}
-.rowname, th {
-    background-color: #ccc;
-}
-td {
-    padding: 0.4em;
-}
-.bad{
-    background-color: #f9d7dc;
-}
-.good{
-    background-color: #c7f0d2;
-}
-.warn{
-    background-color: orange;
-}
-fieldset {
-    display: inline;
-    margin: 1em;
-    padding: 1em;
-}
-</style>
-<table>
+        self.s = """
 <tr>
-<th>File</th><th>Lexer</th>""")
-for p in args.passes:
-    res_html.write("<th>{}</th>\n".format(p))
-res_html.write("""
-</tr>
-""")
+        <td class="rowname">
+           <a href="{}.html">{}</a>
+        <input class="w3-btn" id='toggle{}' type="button" onclick="toggle('{}')" value="+"/>
+        </td>
+        {}
+</tr>""".format(self.filename, self.filename,
+                self.filename, self.filename, self.s) + "\n"
 
-def k(t):
-    return (t.lastcorrectstep,t.f)
-
-threads = sorted(threads, key=k, reverse=False)
-
-for t in threads:
-    res_html.write(t.s)
-res_html.close()
-
-numtotal = len(threads)
-ok = [t for t in threads if t.lastcorrectstep == numcols-2]
-ko = [t for t in threads if t.lastcorrectstep != numcols-2]
-
-print("{}/{} OK.".format(len(ok), numtotal))
-print("{}/{} KO : {}".format(len(ko), numtotal,list(map((lambda t: (t.f, t.lastcorrectstep)), ko))))
+        self.running = False
 
-if args.verbose >= 1:
-    for t in ko + (ok if args.verbose >= 2 else []):
-        print(t.f)
-        print("STDOUT: \n{}".format(t.stdout))
-        print("STDERR: \n{}".format(t.stderr))
 
+def interrupt_handler(threads):
+    "Interrupt handler"
+    def int_handler(_sig, _frame):
+        "Interrupt handler"
+        print('You pressed Ctrl+C!')
+        for thr in threads:
+            thr.stop()
+    return int_handler
+
+def get_args():
+    "Get arguments"
+    parser = argparse.ArgumentParser()
+    parser.add_argument("-f",
+                        "--file",
+                        help="files to compile",
+                        default=glob.glob("*.e"),
+                        nargs='+')
+    parser.add_argument("-p",
+                        "--passes",
+                        help="passes to execute",
+                        nargs='+',
+                        default=[
+                            "e-run", "cfg-run", "cfg-run-after-cp",
+                            "cfg-run-after-dae", "cfg-run-after-ne", "rtl-run",
+                            "linear-run", "linear-run-after-dse", "ltl-run",
+                            "riscv-run"
+                        ])
+    parser.add_argument("--args",
+                        help="args for programs",
+                        nargs='+',
+                        default=["14", "12", "3", "8", "12"])
+    parser.add_argument("--html", help="Output HTML file", default="results.html")
+    parser.add_argument("-d",
+                        "--dry-run",
+                        help="Dry-run. Don't actually compile anything",
+                        action="store_true")
+    parser.add_argument("-v",
+                        "--verbose",
+                        help="Verbosity level",
+                        action="count",
+                        default=0)
+    parser.add_argument("--make-expect",
+                        help="Make .expect files for each test",
+                        action="store_true")
+    args, unknown_args = parser.parse_known_args()
+    return args, unknown_args
+
+def main():
+    "Main function"
+    args, unknown_args = get_args()
+    # show options
+    if args.verbose >= 1:
+        print("args.file=" + str(args.file))
+        print("args.passes=" + str(args.passes))
+        print("args.args=" + str(args.args))
+        print("args.html=" + str(args.html))
+        print("args.dry_run=" + str(args.dry_run))
+        print("args.verbose=" + str(args.verbose))
+
+    # construct the set of commands to be launched, one per file
+    cmds = []
+    for fname in args.file:
+        cmd = "../ecomp -json {f}.json -f {f} {passes} {uargs} -- {args}"
+        cmd = cmd.format(passes=" ".join(map(lambda s: "-" + s, args.passes)),
+                         uargs=" ".join(unknown_args),
+                         args=" ".join(args.args),
+                         f=fname)
+        cmds.append((fname, cmd))
+
+    # dyr_run : simply show the commands but don't execute them
+    if args.dry_run:
+        for (_, cmd) in cmds:
+            print(cmd)
+        sys.exit()
+
+    # The list of threads that will be launched
+    threads: List[Thread] = []
+
+
+
+    signal.signal(signal.SIGINT, interrupt_handler(threads))
+
+    for (fname, cmd) in cmds:
+        exec_thread = CommandExecutor(fname, cmd,
+                                      args.args, args.make_expect,
+                                      # 1 colonne pour le lexer
+                                      len(args.passes) + 1)
+        threads.append(exec_thread)
+        exec_thread.start()
+
+    print("Before launching displayer: {} threads".format(len(threads)))
+
+    disp_thread = Displayer(list(threads))
+    disp_thread.start()
+
+    for thr in threads:
+        thr.join()
+
+    disp_thread.join()
+    print("After displayer: {} threads".format(len(threads)))
+    print("All threads terminated!")
+
+    res_html = open(args.html, "w")
+    res_html.write("""
+    <html>
+    <head>
+    <link rel="stylesheet" href="w3.css">
+    <script src="https://kit.fontawesome.com/1f5d81749b.js" crossorigin="anonymous"></script>
+    <style type="text/css">
+    /*
+    table , table th, table td , table tr{
+        border: 1px solid black;
+        border-collapse: collapse;
+        text-align: center;
+    }
+    .rowname, th {
+        background-color: #ccc;
+    }
+    td {
+        padding: 0.4em;
+    }
+    .bad{
+        background-color: #f9d7dc;
+    }
+    .good{
+        background-color: #c7f0d2;
+    }
+    .warn{
+        background-color: orange;
+    }
+    
+    fieldset {
+        display: inline;
+        margin: 1em;
+        padding: 1em;
+    }*/
+    </style>
+    <script type="text/javascript">
+    function toggleVisibility(elt){
+      if (elt.style.display == 'none')
+        elt.style.display = 'block';
+      else
+        elt.style.display = 'none';
+    }
+
+    function toggle(name){
+      var elts = document.getElementsByName(name);
+      console.log(elts);
+      for (var k = 0; k < elts.length; k++){
+        toggleVisibility(elts[k]);
+      }
+      var x = document.getElementById('toggle'+name);
+      if (x.value == '+') x.value = '-';
+      else x.value = '+';
+    }
+    </script>
+    </head>
+    <body>""")
+
+    now = datetime.datetime.now()
+    res_html.write ("{}".format(now))
+
+    res_html.write("""
+    <table class="w3-table w3-striped w3-responsive">
+    <tr><th>File</th>""")
+    for pass_name in ["Lexer"] + args.passes:
+        res_html.write("<th style='transform: rotate(180deg); writing-mode: vertical-rl;'>{}</th>\n".format(pass_name))
+    res_html.write("""
+    </tr>
+    """)
+
+    print("Before sorting: {} threads".format(len(threads)))
+    threads = sorted(threads, key=lambda t: (t.lastcorrectstep, t.filename), reverse=False)
+    print("After sorting: {} threads".format(len(threads)))
+    for thr in threads:
+        res_html.write(thr.s)
+        res_html.write("\n")
+    res_html.write("</table>\n")
+    res_html.write("</body>\n")
+    res_html.write("</html>\n")
+    res_html.close()
+
+    numtotal = len(threads)
+    thr_ok = [t for t in threads if t.lastcorrectstep == len(args.passes) - 1]
+    thr_ko = [t for t in threads if t.lastcorrectstep != len(args.passes) - 1]
+
+    print("{}/{} OK.".format(len(thr_ok), numtotal))
+    print("{}/{} KO : {}".format(
+        len(thr_ko), numtotal, list(map((lambda t: (t.filename, t.lastcorrectstep)), thr_ko))))
+
+    if args.verbose >= 1:
+        for thr in thr_ko + (thr_ok if args.verbose >= 2 else []):
+            print(thr.filename)
+            print("STDOUT: \n{}".format(thr.stdout))
+            print("STDERR: \n{}".format(thr.stderr))
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/w3.css b/tests/w3.css
new file mode 100644
index 0000000000000000000000000000000000000000..08cad907ac3643704fdd4369b5545b4b821e3760
--- /dev/null
+++ b/tests/w3.css
@@ -0,0 +1,235 @@
+/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
+html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
+/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
+html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
+article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
+audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
+audio:not([controls]){display:none;height:0}[hidden],template{display:none}
+a{background-color:transparent}a:active,a:hover{outline-width:0}
+abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
+b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
+small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
+code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
+button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
+button,input{overflow:visible}button,select{text-transform:none}
+button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
+button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
+button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
+fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
+legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
+[type=checkbox],[type=radio]{padding:0}
+[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
+[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
+[type=search]::-webkit-search-decoration{-webkit-appearance:none}
+::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
+/* End extract */
+html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
+h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
+.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
+h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
+hr{border:0;border-top:1px solid #eee;margin:20px 0}
+.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
+.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
+.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
+.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
+.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
+.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
+.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
+.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
+.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
+.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}   
+.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
+.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
+.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
+.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
+.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
+.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
+.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
+.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
+.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
+.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
+.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
+.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
+.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
+.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
+.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
+.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
+.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
+.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
+.w3-main,#main{transition:margin-left .4s}
+.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
+.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
+.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
+.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
+.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
+.w3-bar .w3-button{white-space:normal}
+.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
+.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
+.w3-responsive{display:block;overflow-x:auto}
+.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
+.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
+.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
+.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
+.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
+.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
+@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
+.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
+.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
+@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
+.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
+.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
+.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
+.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
+.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
+.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
+.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
+@media (max-width:1205px){.w3-auto{max-width:95%}}
+@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
+.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}	
+.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
+.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
+@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
+@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
+@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
+@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
+.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
+.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
+.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
+.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
+.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
+.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
+.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
+.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
+.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
+.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
+.w3-display-position{position:absolute}
+.w3-circle{border-radius:50%}
+.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
+.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
+.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
+.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
+.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
+.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
+.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
+.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
+.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
+.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
+.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
+.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
+.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
+.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
+.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
+.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
+.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
+.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
+.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
+.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
+.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
+.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
+.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
+.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
+.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
+.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
+.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
+.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
+.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
+.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
+.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
+.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
+.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
+.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
+.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
+.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
+.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
+.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
+.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
+.w3-left{float:left!important}.w3-right{float:right!important}
+.w3-button:hover{color:#000!important;background-color:#ccc!important}
+.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
+.w3-hover-none:hover{box-shadow:none!important}
+/* Colors */
+.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
+.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
+.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
+.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
+.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
+.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
+.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
+.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
+.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
+.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
+.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
+.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
+.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
+.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
+.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
+.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
+.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
+.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
+.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
+.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
+.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
+.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
+.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
+.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
+.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
+.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
+.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
+.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
+.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
+.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
+.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
+.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
+.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
+.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
+.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
+.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
+.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
+.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
+.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
+.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
+.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
+.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
+.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
+.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
+.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
+.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
+.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
+.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
+.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
+.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
+.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
+.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
+.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
+.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
+.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
+.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
+.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
+.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
+.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
+.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
+.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
+.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
+.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
+.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
+.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
+.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
+.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
+.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
+.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
+.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
+.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
+.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
+.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
+.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
+.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
+.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
+.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
+.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
+.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
+.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
+.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
+.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
+.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
+.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}