diff --git a/src/mlw/cprinter.ml b/src/mlw/cprinter.ml
index 2da401344b9cf2a60e8e63cc30164e9ff3ec2289..cf51109b34a14e5129c34df5cca3fc168863a340 100644
--- a/src/mlw/cprinter.ml
+++ b/src/mlw/cprinter.ml
@@ -1,18 +1,18 @@
 open Ident
 
 exception Unsupported of string
-exception NoSyntax of string
 
 module C = struct
 
   type ty =
     | Tvoid
-    | Tsyntax of string * ty list (* ints, floats, doubles, chars are here *)
+    | Tsyntax of string * ty list
     | Tptr of ty
     | Tarray of ty * expr
     | Tstruct of ident * (ident * ty) list
     | Tunion of ident * (ident * ty) list
     | Tnamed of ident (* alias from typedef *)
+    | Tnosyntax (* types that do not have a syntax, can't be printed *)
     (* enum, const could be added *)
 
   (* int x=2, *y ... *)
@@ -66,7 +66,6 @@ module C = struct
     | Dproto of ident * proto
     | Ddecl of names
     | Dtypedef of ty * ident
-    | Dstructural of names (* struct, union... *)
 
   and body = definition list * stmt
 
@@ -141,9 +140,6 @@ module C = struct
     | Dfun _ -> raise (Unsupported "nested function")
     | Dtypedef _ -> raise (Unsupported "typedef inside function")
     | Dproto _ -> raise (Unsupported "prototype inside function")
-    | Dstructural (ty,l) ->
-      let l,b = aux l in
-      Dstructural (ty, l), b
 
   and propagate_in_block id v (dl, s) =
     let dl, b = List.fold_left
@@ -156,7 +152,8 @@ module C = struct
       ([],true) dl in
     (List.rev dl, if b then propagate_in_stmt id v s else s)
 
-
+  let is_empty_block s = s = Sblock([], Snop)
+  let block_of_expr e = [], Sexpr e
 end
 
 type info = Pdriver.printer_args = private {
@@ -189,77 +186,91 @@ module Translate = struct
        begin match query_syntax info.syntax ts.ts_name
         with
         | Some s -> C.Tsyntax (s, List.map (ty_of_ty info) tl)
-        | None -> raise (NoSyntax ts.ts_name.id_string)
+        | None -> C.Tnosyntax
        end
 
   let pv_name pv = pv.pv_vs.vs_name
 
-  let rec expr info (e:expr) : C.body =
-    match e.e_node with
-    | Evar pv -> C.([], Sexpr(Evar (pv_name pv)))
+  let rec expr info ?(is_return=false) (e:expr) : C.body =
+    if e_ghost e then (Format.printf "translating ghost expr@."; C.([], Snop))
+    else if is_e_void e then C.([], Snop)
+    else if is_e_true e then expr info ~is_return (e_nat_const 1)
+    else if is_e_false e then expr info ~is_return (e_nat_const 0)
+    else match e.e_node with
+    | Evar pv ->
+       let e = C.Evar(pv_name pv) in
+       C.([], if is_return then Sreturn e else Sexpr e)
     | Econst (Number.ConstInt ic) ->
       let n = Number.compute_int ic in
-      C.([], Sexpr(Econst (Cint (BigInt.to_string n))))
-    | Econst _ -> assert false (*TODO*)
+      let e = C.(Econst (Cint (BigInt.to_string n))) in
+      C.([], if is_return then Sreturn e else Sexpr e)
+    | Econst _ -> raise (Unsupported "real constants")
     | Eexec (ce, _cty) ->
       begin match ce.c_node with
-      | Cfun e -> expr info e
+      | Cfun e -> expr info ~is_return e
       | Capp (rs, pvsl) ->
-        begin match query_syntax info.syntax rs.rs_name with
-        | Some s ->
-          let params = List.map
-            (fun pv -> (C.Evar(pv_name pv), ty_of_ty info (ty_of_ity pv.pv_ity)))
-            pvsl in
-          let rty = ty_of_ity rs.rs_cty.cty_result in
-          let rtyargs = match rty.ty_node with
-            | Tyvar _ -> [||]
-            | Tyapp (_,args) -> Array.of_list (List.map (ty_of_ty info) args)
-          in
-          C.([], Sexpr(Esyntax(s,ty_of_ty info rty, rtyargs, params)))
-        | None ->
-          let args = List.filter (fun pv -> not pv.pv_ghost) pvsl in
-          C.([],
-             Sexpr(Ecall(Evar(rs.rs_name),
-                         List.map (fun pv -> Evar(pv_name pv)) args)))
-        end
-      | _ -> assert false
+         let e =  match query_syntax info.syntax rs.rs_name with
+           | Some s ->
+              let params =
+		List.map (fun pv -> (C.Evar(pv_name pv), ty_of_ty info (ty_of_ity pv.pv_ity)))
+			 pvsl in
+              let rty = ty_of_ity rs.rs_cty.cty_result in
+              let rtyargs = match rty.ty_node with
+		| Tyvar _ -> [||]
+		| Tyapp (_,args) -> Array.of_list (List.map (ty_of_ty info) args)
+              in
+              C.Esyntax(s,ty_of_ty info rty, rtyargs, params)
+           | None ->
+              let args = List.filter (fun pv -> not pv.pv_ghost) pvsl in
+              C.(Ecall(Evar(rs.rs_name), List.map (fun pv -> Evar(pv_name pv)) args))
+         in
+	 C.([], if is_return then Sreturn e else Sexpr e)
+      | _ -> raise (Unsupported "Cpur/Cany") (*TODO clarify*)
       end
     | Eassign _ -> raise (Unsupported "mutable field assign")
     | Elet (ld,e) ->
       begin match ld with
       | LDvar (pv,le) ->
         Format.printf "let %s@." pv.pv_vs.vs_name.id_string;
-        if pv.pv_ghost then expr info e
+        if pv.pv_ghost then expr info ~is_return e
         else if ((pv_name pv).id_string = "_" && ity_equal pv.pv_ity ity_unit)
-        then ([], C.Sseq (C.Sblock(expr info le), C.Sblock(expr info e)))
+        then ([], C.Sseq (C.Sblock(expr info ~is_return:false le),
+			  C.Sblock(expr info ~is_return e)))
         else begin
           match le.e_node with
           | Econst (Number.ConstInt ic) ->
             let n = Number.compute_int ic in
             let cexp = C.(Econst (Cint (BigInt.to_string n))) in
-            C.propagate_in_block (pv_name pv) cexp (expr info e)
+	    Format.printf "propagate constant %s for var %s@."
+			  (BigInt.to_string n) (pv_name pv).id_string;
+            C.propagate_in_block (pv_name pv) cexp (expr info ~is_return e)
           | _->
             let t = ty_of_ty info (ty_of_ity pv.pv_ity) in
-            let initblock = expr info le in
+            let d,s = expr info ~is_return:false le in
+	    let initblock = d, C.assignify (pv_name pv) s in
             [ C.Ddecl (t, [pv_name pv, C.Enothing]) ],
-            C.Sseq (C.Sblock initblock, C.Sblock (expr info e))
+            C.Sseq (C.Sblock initblock, C.Sblock (expr info ~is_return e))
         end
       | _ -> assert false
       end
-    | Eif (c, t, e) ->
-      let t = expr info t in
-      let e = expr info e in
-      begin match expr info c with
-      | [], C.Sexpr c -> [], C.Sif(c,C.Sblock t, C.Sblock e)
-      | cblock ->
-        let cid = id_register (id_fresh "cond") in (* ? *)
-        [ C.Ddecl (C.Tsyntax ("int",[]), [cid, C.Enothing]) ],
-        C.Sseq (C.Sblock cblock, C.Sif (C.Evar cid, C.Sblock t, C.Sblock e))
-      (* TODO detect empty branches and replace with Snop*)
-      end
+    | Eif (cond, th, el) ->
+       let c = expr info ~is_return:false cond in
+       let t = expr info ~is_return th in
+       let e = expr info ~is_return el in
+       begin match c with
+	     | [], C.Sexpr c ->
+		if is_e_false th && is_e_true el
+		then C.([], Sexpr(Eunop(Unot, c)))
+		else [], C.Sif(c,C.Sblock t, C.Sblock e)
+	     | cdef, cs ->
+		let cid = id_register (id_fresh "cond") in (* ? *)
+		C.Ddecl (C.Tsyntax ("int",[]), [cid, C.Enothing])::cdef,
+		C.Sseq (C.assignify cid cs, C.Sif (C.Evar cid, C.Sblock t, C.Sblock e))
+       (* TODO detect empty branches and replace with Snop, detect and/or*)
+       end
     | Ewhile (c,_,_,e) ->
-      let cd, cs = expr info c in
-      let b = expr info e in
+      let cd, cs = expr info ~is_return:false c in
+      let b = expr info ~is_return:false e in
       begin match cs with
       | C.Sexpr ce -> cd, C.Swhile (ce, C.Sblock b)
       | _ ->
@@ -268,36 +279,32 @@ module Translate = struct
         C.Sseq (C.Sblock (cd, cs), C.Swhile (C.Evar cid, C.Sblock b))
       end
     | Etry _ | Eraise _ -> raise (Unsupported "try/exceptions") (*TODO*)
-    | Efor _ -> assert false (*TODO*)
+    | Efor _ -> raise (Unsupported "for loops")  (*TODO*)
     | Eassert _ -> [], C.Snop
-    | Eghost _ | Epure _ | Ecase _ | Eabsurd -> assert false
+    | Ecase _ -> raise (Unsupported "pattern matching")
+    | Eghost _ | Epure _ | Eabsurd -> assert false
 
   let pdecl info (pd:Pdecl.pdecl) : C.definition list =
     match pd.pd_node with
     | PDlet (LDsym (rs, ce)) ->
       let fname = rs.rs_name in
       Format.printf "PDlet rsymbol %s@." fname.id_string;
-      begin try
-        if Mid.mem fname info.syntax then (Format.printf "has syntax@."; [])
-        else
+      if Mid.mem fname info.syntax then (Format.printf "has syntax@."; [])
+      else
         let params = List.map
-          (fun pv -> ty_of_ty info pv.pv_vs.vs_ty, pv_name pv)
-          (List.filter
-             (fun pv -> not pv.pv_ghost && not (ity_equal pv.pv_ity ity_unit))
-             rs.rs_cty.cty_args) in
-        match ce.c_node with
+		       (fun pv -> ty_of_ty info pv.pv_vs.vs_ty, pv_name pv)
+		       (List.filter
+			  (fun pv -> not pv.pv_ghost && not (ity_equal pv.pv_ity ity_unit))
+			  rs.rs_cty.cty_args) in
+        begin match ce.c_node with
         | Cfun e ->
-          let rity = rs.rs_cty.cty_result in
-          let rtype =
-            if ity_equal rity ity_unit then C.Tvoid
-            else ty_of_ty info (ty_of_ity rity) in
-          [C.Dfun (fname, (rtype,params), expr info e)]
+           let rity = rs.rs_cty.cty_result in
+           let rtype =
+             if ity_equal rity ity_unit then C.Tvoid
+             else ty_of_ty info (ty_of_ity rity) in
+           [C.Dfun (fname, (rtype,params), expr info ~is_return:true e)]
         | _ -> raise (Unsupported "Non-function with no syntax in toplevel let")
-        with
-          NoSyntax s ->
-            Format.printf "%s has no syntax : not extracted@." s;
-            []
-      end
+	end
     | PDtype [{itd_its = its}] ->
       let id = its.its_ts.ts_name in
       Format.printf "PDtype %s@." id.id_string;
@@ -317,7 +324,7 @@ module Translate = struct
 
   let munit info = function
     | Udecl pd -> pdecl info pd
-    | Uuse _ -> []
+    | Uuse m -> [C.Dinclude m.mod_theory.Theory.th_name]
     | Uclone _ -> raise (Unsupported "clone")
     | Umeta _ -> raise (Unsupported "meta")
     | Uscope _ -> []
@@ -329,9 +336,8 @@ module Translate = struct
     with
     | Unsupported s ->
       Format.printf "Failed because of unsupported construct: %s@." s; []
-    | NoSyntax s ->
-      Format.printf "Failed because %s has no syntax@." s; []
 end
+(*TODO simplifications : propagate constants, collapse blocks with only a statement and no def*)
 
 module Print = struct
 
@@ -355,7 +361,7 @@ module Print = struct
 
   let rec print_ty ?(paren=false) fmt = function
     | Tvoid -> fprintf fmt "void"
-    | Tsyntax (s, tl) -> syntax_arguments s print_ty fmt tl
+    | Tsyntax (s, tl) -> syntax_arguments s (print_ty ~paren:false) fmt tl
     | Tptr ty -> fprintf fmt "(%a)*" (print_ty ~paren:true) ty
     | Tarray (ty, expr) ->
       fprintf fmt (protect_on paren "%a[%a]")
@@ -363,6 +369,7 @@ module Print = struct
     | Tstruct _ -> raise (Unprinted "structs")
     | Tunion _ -> raise (Unprinted "unions")
     | Tnamed id -> print_ident fmt id
+    | Tnosyntax -> raise (Unprinted "type without syntax")
 
   and print_unop fmt = function
     | Unot -> fprintf fmt "!"
@@ -377,9 +384,9 @@ module Print = struct
     | Bassign -> fprintf fmt "="
 
   and print_expr ?(paren=false) fmt = function
-    | Enothing -> ()
+    | Enothing -> Format.printf "enothing"; ()
     | Eunop(u,e) -> fprintf fmt (protect_on paren "%a %a")
-      print_unop u (print_expr ~paren) e
+      print_unop u (print_expr ~paren:true) e
     | Ebinop(b,e1,e2) ->
       fprintf fmt (protect_on paren "%a %a %a")
         (print_expr ~paren:true) e1 print_binop b (print_expr ~paren:true) e2
@@ -396,39 +403,69 @@ module Print = struct
       fprintf fmt (protect_on paren "sizeof(%a)") (print_ty ~paren:false) ty
     | Eindex _ | Edot _ | Earrow _ -> raise (Unprinted "struct/array access")
     | Esyntax (s, t, args, lte) ->
-      gen_syntax_arguments_typed snd (fun _ -> args) s
-        (fun fmt (e,t) -> print_expr ~paren:false fmt e)
+      gen_syntax_arguments_typed snd (fun _ -> args)
+        (if paren then ("("^s^")") else s)
+        (fun fmt (e,_t) -> print_expr ~paren:false fmt e)
         (print_ty ~paren:false) (C.Enothing,t) fmt lte
 
   and print_const  fmt = function
     | Cint s | Cfloat s | Cchar s | Cstring s -> fprintf fmt "%s" s
 
+  let print_id_init fmt = function
+    | id, Enothing -> print_ident fmt id
+    | id,e -> fprintf fmt "%a = %a" print_ident id (print_expr ~paren:false) e
 
   let rec print_stmt fmt = function
-    | Snop -> ()
-    | Sexpr e -> fprintf fmt "%a;@;" (print_expr ~paren:false) e;
-    | Sblock b -> fprintf fmt "@[<hv>{@;<1 2>@[<hv>%a@]@;}@;@]@;" print_body b
-    | Sseq (s1,s2) -> fprintf fmt "@[<v>%a@;%a@]" print_stmt s1 print_stmt s2
-    | Sif (c,t,e) -> fprintf fmt "if(%a) @ %aelse@ %a"
+    | Snop -> Format.printf "snop"; ()
+    | Sexpr e -> fprintf fmt "%a;" (print_expr ~paren:false) e;
+    | Sblock b -> fprintf fmt "@[<hv>{@;<1 2>@[<hv>%a@]@\n}@]" print_body b
+    | Sseq (s1,s2) -> fprintf fmt "%a@\n%a" print_stmt s1 print_stmt s2
+    | Sif(c,t,e) when is_empty_block e ->
+       fprintf fmt "if(%a)@\n%a" (print_expr ~paren:false) c print_stmt t
+    | Sif (c,t,e) -> fprintf fmt "if(%a)@\n%a@\nelse@\n%a"
       (print_expr ~paren:false) c print_stmt t print_stmt e
     | Swhile (e,b) -> fprintf fmt "while (%a)@ %a"
       (print_expr ~paren:false) e print_stmt b
     | Sfor _ -> raise (Unprinted "for loops")
-    | Sbreak -> fprintf fmt "break;@;"
-    | Sreturn e -> fprintf fmt "return %a;@;" (print_expr ~paren:true) e
+    | Sbreak -> fprintf fmt "break;"
+    | Sreturn e -> fprintf fmt "return %a;" (print_expr ~paren:true) e
 
   and print_def fmt = function
     | Dfun (id,(rt,args),body) ->
-      fprintf fmt "%a %a(@[%a@])@ @[<hv>{@;<1 2>@[<hv>%a@]@;}@;@]"
+       fprintf fmt "%a %a(@[%a@])@ @[<hv>{@;<1 2>@[<hv>%a@]@;}@;@]"
+               (print_ty ~paren:false) rt
+               print_ident id
+               (print_list comma
+			   (print_pair_delim nothing space nothing
+					     (print_ty ~paren:false) print_ident))
+	       args
+               print_body body
+    | Dproto (id, (rt, args)) ->
+      fprintf fmt "%a %a(@[%a@]);@;"
         (print_ty ~paren:false) rt
         print_ident id
         (print_list comma
-           (print_pair_delim nothing space nothing print_ty print_ident)) args
-        print_body body
-    | _ -> assert false
+           (print_pair_delim nothing space nothing
+			     (print_ty ~paren:false) print_ident))
+	args
+    | Ddecl (ty, lie) ->
+       fprintf fmt "%a @[<hov>%a@];@;"
+	       (print_ty ~paren:false) ty
+	       (print_list comma print_id_init) lie
+    | Dinclude id ->
+       fprintf fmt "#include<%a>@;" print_ident id
+    | Dtypedef (ty,id) ->
+       fprintf fmt "@[<hov>typedef@ %a@;%a;@]@;"
+	       (print_ty ~paren:false) ty print_ident id
+
+  and print_body fmt body =
+    print_pair_delim nothing newline nothing
+		     (print_list newline print_def)
+		     print_stmt
+		     fmt body
+
+  let print_file fmt = fprintf fmt "@[<v>%a@]@." (print_list newline print_def)
 
-  and print_body fmt = function
-    | _ -> assert false
 
 end
 
@@ -438,21 +475,11 @@ let fg ?fname m =
   | None -> n ^ ".c"
   | Some f -> f ^ "__" ^ n ^ ".c"
 
-open Format
-
 let pr args ?old fmt m =
   ignore(old);
-  let _ast = Translate.translate args m in
-  (* TODO:
-    iterer sur m.mod_units la fonction pr_unit
-   *)
-
-  fprintf fmt "#include <stdio.h>\n\
-\n\
-int main() {\n\
-  printf \"Extraction from WhyML to C not yet implemented\\n\";\n\
-  return 1;\n\
-}\n\
-"
+  let ast = Translate.translate args m in
+  try Print.print_file fmt ast
+  with Print.Unprinted s -> (Format.printf "Could not print: %s@." s;
+		       Format.fprintf fmt "/* Dummy file */@.")
 
 let () = Pdriver.register_printer "c" ~desc:"printer for C code" fg pr