diff --git a/expr_grammar_action.g b/expr_grammar_action.g
index 60a5b346c730e1e52747422107298a79f1a451a2..0ccce0ebe6406a10f46a3fc9ebc710b6f7c673e5 100644
--- a/expr_grammar_action.g
+++ b/expr_grammar_action.g
@@ -2,6 +2,7 @@ tokens SYM_EOF SYM_IDENTIFIER<string> SYM_INTEGER<int> SYM_PLUS SYM_MINUS SYM_AS
 tokens SYM_LPARENTHESIS SYM_RPARENTHESIS SYM_LBRACE SYM_RBRACE
 tokens SYM_ASSIGN SYM_SEMICOLON SYM_RETURN SYM_IF SYM_WHILE SYM_ELSE SYM_COMMA
 tokens SYM_EQUALITY SYM_NOTEQ SYM_LT SYM_LEQ SYM_GT SYM_GEQ
+tokens SYM_INT SYM_CHAR SYM_VOID SYM_CHARACTER<char>
 non-terminals S INSTR<tree> INSTRS<tree list> LINSTRS ELSE EXPR FACTOR
 non-terminals LPARAMS REST_PARAMS
 non-terminals IDENTIFIER INTEGER
@@ -12,6 +13,7 @@ non-terminals CMP_EXPRS CMP_EXPR
 non-terminals EQ_EXPRS EQ_EXPR
 
 non-terminals AFTER_IDENTIFIER_INSTR AFTER_IDENTIFIER_FACTOR LARGS REST_ARGS
+non-terminals TYPE AFTER_IDENTIFIER_DEC CHARACTER
 
 axiom S
 {
@@ -40,11 +42,15 @@ rules
 S -> FUNDEFS SYM_EOF { Node(Tlistglobdef, $1) }
 FUNDEFS -> FUNDEF FUNDEFS { $1::$2 }
 FUNDEFS -> { [] }
-FUNDEF -> IDENTIFIER SYM_LPARENTHESIS LPARAMS SYM_RPARENTHESIS INSTR { Node(Tfundef, [Node(Tfunname, [$1]); Node(Tfunargs, $3); Node(Tfunbody, [$5])]) }
+FUNDEF -> TYPE IDENTIFIER SYM_LPARENTHESIS LPARAMS SYM_RPARENTHESIS INSTR { Node(Tfundef, [Node(Tfuntype, [$1]); Node(Tfunname, [$2]); Node(Tfunargs, $4); Node(Tfunbody, [$6])]) }
 
-LPARAMS -> IDENTIFIER REST_PARAMS { Node(Targ, [$1])::$2 }
+TYPE -> SYM_INT { TypeLeaf Tint }
+TYPE -> SYM_CHAR { TypeLeaf Tchar }
+TYPE -> SYM_VOID { TypeLeaf Tvoid }
+
+LPARAMS -> TYPE IDENTIFIER REST_PARAMS { Node(Targ, [$1; $2])::$3 }
 LPARAMS -> { [] }
-REST_PARAMS -> SYM_COMMA IDENTIFIER REST_PARAMS { Node(Targ, [$2])::$3 }
+REST_PARAMS -> SYM_COMMA TYPE IDENTIFIER REST_PARAMS { Node(Targ, [$2; $3])::$4 }
 REST_PARAMS -> { [] }
 
 LARGS -> EXPR REST_ARGS { $1::$2 }
@@ -66,11 +72,20 @@ INSTR -> IDENTIFIER AFTER_IDENTIFIER_INSTR SYM_SEMICOLON {
   | Funcall args -> Node(Tcall, [$1; Node(Targs, args)]) 
   | _ -> $1 
 }
+INSTR -> TYPE IDENTIFIER AFTER_IDENTIFIER_DEC SYM_SEMICOLON {
+  match $3 with
+  | Assign exp -> Node(Tblock, [Node(Tdeclare, [$1; $2]); Node(Tassign, [$2; exp])])
+  | Nothing -> Node(Tdeclare, [$1; $2])
+  | _ -> $1
+}
 INSTR -> SYM_LBRACE LINSTRS SYM_RBRACE { $2 }
 
 AFTER_IDENTIFIER_INSTR -> SYM_ASSIGN EXPR { Assign $2 }
 AFTER_IDENTIFIER_INSTR -> SYM_LPARENTHESIS LARGS SYM_RPARENTHESIS { Funcall $2 }
 
+AFTER_IDENTIFIER_DEC -> SYM_ASSIGN EXPR { Assign $2 }
+AFTER_IDENTIFIER_DEC -> { Nothing }
+
 ELSE -> SYM_ELSE SYM_LBRACE LINSTRS SYM_RBRACE { $3 }
 ELSE -> { NullLeaf }
 
@@ -109,9 +124,11 @@ FACTOR -> IDENTIFIER AFTER_IDENTIFIER_FACTOR {
   | _ -> $1
 }
 FACTOR -> SYM_LPARENTHESIS EXPR SYM_RPARENTHESIS { $2 }
+FACTOR -> CHARACTER { $1 }
 
 IDENTIFIER -> SYM_IDENTIFIER {StringLeaf $1}
 INTEGER -> SYM_INTEGER {IntLeaf $1}
+CHARACTER -> SYM_CHARACTER {CharLeaf $1}
 
 AFTER_IDENTIFIER_FACTOR -> { Nothing }
 AFTER_IDENTIFIER_FACTOR -> SYM_LPARENTHESIS LARGS SYM_RPARENTHESIS { Funcall $2 }
diff --git a/src/ast.ml b/src/ast.ml
index 7560fa685835d10dadbf5fdafbd046d46869061c..f8b7689cb10a616932442a94d94d149174843163 100644
--- a/src/ast.ml
+++ b/src/ast.ml
@@ -1,4 +1,5 @@
 open Batteries
+open Prog
 
 (* Les AST sont des arbres, du type [tree], étiquetés par des [tag].
 
@@ -22,14 +23,14 @@ open Batteries
 
 *)
 
-type tag = Tassign | Tif | Twhile | Tblock | Treturn
-         | Tint
+type tag = Tassign | Tif | Twhile | Tblock | Treturn | Tdeclare
+         | Tint | Tchar | Tvoid
          | Tadd | Tmul | Tdiv | Tmod | Txor | Tsub
          | Tclt | Tcgt | Tcle | Tcge | Tceq | Tne
          | Tneg
          | Tlistglobdef
-         | Tfundef | Tfunname | Tfunargs | Tfunbody | Tcall
-         | Tassignvar
+         | Tfundef | Tfuntype | Tfunname | Tfunargs | Tfunbody | Tcall
+         | Tassignvar (*never used*)
          | Targ | Targs
 
 type tree = | Node of tag * tree list
@@ -37,7 +38,7 @@ type tree = | Node of tag * tree list
             | IntLeaf of int
             | NullLeaf
             | CharLeaf of char
-
+            | TypeLeaf of typ
 let string_of_stringleaf = function
   | StringLeaf s -> s
   | _ -> failwith "string_of_stringleaf called on non-stringleaf nodes."
@@ -74,6 +75,10 @@ let string_of_tag = function
   | Targ -> "Targ"
   | Tcall -> "Tcall"
   | Targs -> "Targs"
+  | Tdeclare -> "Tdeclare"
+  | Tfuntype -> "Tfuntype"
+  | Tchar -> "Tchar"
+  | Tvoid -> "Tvoid"
 
 (* Écrit un fichier .dot qui correspond à un AST *)
 let rec draw_ast a next =
@@ -100,7 +105,8 @@ let rec draw_ast a next =
     (next, next+1, [         Format.sprintf "n%d [label=\"null\"]\n" next])
   | CharLeaf i ->
     (next, next+1, [         Format.sprintf "n%d [label=\"%c\"]\n" next i])
-
+  | TypeLeaf t ->
+    (next, next+1, [         Format.sprintf "n%d [label=\"%s\"]\n" next (string_of_typ t)])
 let draw_ast_tree oc ast =
   let (_, _, s) = draw_ast ast 1 in
   let s = String.concat "" s in
@@ -115,3 +121,4 @@ let rec string_of_ast a =
   | IntLeaf i -> Format.sprintf "%d" i
   | CharLeaf i -> Format.sprintf "%c" i
   | NullLeaf -> "null"
+  | TypeLeaf t -> string_of_typ t
\ No newline at end of file
diff --git a/src/cfg_gen.ml b/src/cfg_gen.ml
index f009b7baa4fbec07ee8334469e65bccd2e2ea279..5831632089eee520c8f75837a274ef4672a0bdfe 100644
--- a/src/cfg_gen.ml
+++ b/src/cfg_gen.ml
@@ -28,6 +28,7 @@ let rec cfg_expr_of_eexpr (e: Elang.expr) : expr res =
   | Elang.Ecall (f, args) -> 
     list_map_res cfg_expr_of_eexpr args >>= fun es ->
     OK (Ecall (f, es))
+  | Elang.Echar c -> OK (Eint (Char.code c))
 
 (* [cfg_node_of_einstr next cfg succ i] builds the CFG node(s) that correspond
    to the E instruction [i].
@@ -73,7 +74,7 @@ let rec cfg_node_of_einstr (next: int) (cfg : (int, cfg_node) Hashtbl.t)
     list_map_res cfg_expr_of_eexpr args >>= fun es ->
     Hashtbl.replace cfg next (Ccall (f, es, succ));
     OK (next, next + 1)
-    
+  | Elang.Ideclare (_, s) -> cfg_node_of_einstr next cfg succ (Elang.Iassign (s, Eint 0))
 
 (* Some nodes may be unreachable after the CFG is entirely generated. The
    [reachable_nodes n cfg] constructs the set of node identifiers that are
@@ -100,7 +101,7 @@ let cfg_fun_of_efun { funargs; funbody } =
   (* remove unreachable nodes *)
   let r = reachable_nodes node cfg in
   Hashtbl.filteri_inplace (fun k _ -> Set.mem k r) cfg;
-  OK { cfgfunargs = funargs;
+  OK { cfgfunargs = List.map (fun (s, t) -> s) funargs;
        cfgfunbody = cfg;
        cfgentry = node;
      }
diff --git a/src/e_regexp.ml b/src/e_regexp.ml
index e909133d0eed77cdfb9933719dd0ad7c48f32cd7..5bba68fcd0cfd8cf36caa0c67dce9d5df302af3a 100644
--- a/src/e_regexp.ml
+++ b/src/e_regexp.ml
@@ -70,7 +70,7 @@ let list_regexp : (regexp * (string -> token option)) list =
     (keyword_regexp "int", fun _ -> Some (SYM_INT));
     (* begin TODO *)
     (keyword_regexp "void",       fun _ -> Some (SYM_VOID));
-    (keyword_regexp "void",       fun _ -> Some (SYM_CHAR));
+    (keyword_regexp "char",       fun _ -> Some (SYM_CHAR));
     (keyword_regexp "if",       fun _ -> Some (SYM_IF));
     (keyword_regexp "else",       fun _ -> Some (SYM_ELSE));
     (keyword_regexp "return",       fun _ -> Some (SYM_RETURN));
diff --git a/src/elang.ml b/src/elang.ml
index 03d287f62c07973da8aa33f72e70b81c18865c5f..f10e95f555781982868b04dc5ea2d79388507006 100644
--- a/src/elang.ml
+++ b/src/elang.ml
@@ -10,6 +10,7 @@ type expr =
   | Eint of int
   | Evar of string
   | Ecall of string * expr list
+  | Echar of char
 
 type instr =
   | Iassign of string * expr
@@ -18,10 +19,13 @@ type instr =
   | Iblock of instr list
   | Ireturn of expr
   | Icall of string * expr list
+  | Ideclare of typ * string
 
 type efun = {
-  funargs: ( string ) list;
+  funargs: ( string * typ ) list;
   funbody: instr;
+  funvartyp : (string, typ) Hashtbl.t;
+  funrettype : typ
 }
 
 type eprog = efun prog
diff --git a/src/elang_gen.ml b/src/elang_gen.ml
index 54e92035f2002c236095886d338e539f505993aa..d191bbd922c1552938c3fd4a48bcdbfa152ede61 100644
--- a/src/elang_gen.ml
+++ b/src/elang_gen.ml
@@ -39,80 +39,118 @@ let binop_of_tag =
   | Tne -> Ecne
   | _ -> assert false
 
+let remove_local_vars typ_var local_typ_var =
+  Hashtbl.filteri (fun s t -> Hashtbl.mem typ_var s) local_typ_var
+      
+let rec type_expr (typ_var : (string,typ) Hashtbl.t) (typ_fun : (string, typ list * typ) Hashtbl.t) (e: expr) : typ res =
+  match e with
+  | Ebinop (b, e1, e2) -> 
+      type_expr typ_var typ_fun e1 >>= fun t1 ->
+      type_expr typ_var typ_fun e2 >>= fun t2 ->
+      if t1 != Tvoid && t2 != Tvoid
+        then OK Tint
+        else Error "E: Binop is not defined on void type."
+  | Eunop (u, e) -> 
+      type_expr typ_var typ_fun e >>= fun t ->
+        if t != Tvoid
+          then OK Tint
+          else Error "E: Unop is not defined on void type."
+  | Eint i -> OK Tint
+  | Echar c -> OK Tchar
+  | Evar s -> 
+    (match Hashtbl.find_option typ_var s with
+    | Some t when t != Tvoid -> OK t
+    | _ -> Error (Format.sprintf "E: Expression %s type is not defined." s))
+  | Ecall (f, _) -> 
+    match Hashtbl.find_option typ_fun f with
+    | Some (_, t) when t != Tvoid -> OK t
+    | _ -> Error "E: Function return type is not defined."
+
+let are_compatible (t1 : typ) (t2 : typ) : bool =
+  match t1, t2 with
+  | Tint, Tint
+  | Tchar, Tchar
+  | Tint, Tchar
+  | Tchar, Tint -> true
+  | _ -> false
+
 (* [make_eexpr_of_ast a] builds an expression corresponding to a tree [a]. If
    the tree is not well-formed, fails with an [Error] message. *)
-let rec make_eexpr_of_ast (a: tree) : expr res =
+let rec make_eexpr_of_ast (typ_var : (string,typ) Hashtbl.t) (typ_fun : (string, typ list * typ) Hashtbl.t) (a: tree) : expr res =
   let res =
     match a with
     (* TODO *)
     | IntLeaf i -> OK (Eint i)
     | StringLeaf s -> OK (Evar s) 
+    | CharLeaf c -> OK (Echar c)
     | Node(t, [e1; e2]) when tag_is_binop t ->
-        (let res1 = make_eexpr_of_ast e1
-          in let res2 = make_eexpr_of_ast e2
-            in match res1, res2 with
-            | Error msg, _ -> Error msg
-            | _, Error msg -> Error msg
-            | OK expr1, OK expr2 -> OK (Ebinop (binop_of_tag t, expr1, expr2)))
+        (make_eexpr_of_ast typ_var typ_fun e1 >>= fun expr1 ->
+        make_eexpr_of_ast typ_var typ_fun e2 >>= fun expr2 ->
+        OK (Ebinop (binop_of_tag t, expr1, expr2)))
     | Node(Tneg, [e]) -> 
-        (let res = make_eexpr_of_ast e
-          in match res with
-          | Error msg -> Error msg
-          | OK expr -> OK (Eunop (Eneg, expr)))
+        make_eexpr_of_ast typ_var typ_fun e >>= fun expr ->
+        OK (Eunop (Eneg, expr))
     | Node(Tcall, [StringLeaf f; Node(Targs, args)]) -> 
-        (let res = list_map_res make_eexpr_of_ast args 
-          in match res with
-          | Error msg -> Error msg
-          | OK exprs -> OK (Ecall (f, exprs)))
+        list_map_res (make_eexpr_of_ast typ_var typ_fun) args >>= fun exprs -> 
+        OK (Ecall (f, exprs))
     | _ -> 
         Error (Printf.sprintf "Unacceptable ast in make_eexpr_of_ast %s"
                     (string_of_ast a))
   in
   match res with
-    OK o -> res
+    OK o -> type_expr typ_var typ_fun o >>= fun t -> res
   | Error msg -> Error (Format.sprintf "In make_eexpr_of_ast %s:\n%s"
                           (string_of_ast a) msg)
 
-let rec make_einstr_of_ast (a: tree) : instr res =
+let rec make_einstr_of_ast (typ_var : (string,typ) Hashtbl.t) (typ_fun : (string, typ list * typ) Hashtbl.t) (a: tree) : instr res =
   let res =
     match a with
     (* TODO *)
     | Node(Tassign, [StringLeaf s; e]) -> 
-      (let res_of_e = make_eexpr_of_ast e 
-        in match res_of_e with 
-        | OK exp -> OK (Iassign (s, exp))
-        | Error msg -> Error msg)
+        make_eexpr_of_ast typ_var typ_fun e >>= fun expr ->
+        type_expr typ_var typ_fun expr >>= fun te ->
+        type_expr typ_var typ_fun (Evar s) >>= fun ts ->
+        if are_compatible te ts 
+          then OK (Iassign (s, expr))
+          else Error (Format.sprintf "E: Types %s and %s are not compatible." (string_of_typ ts) (string_of_typ te))
     | Node(Tif, [e; i1; i2]) -> 
-      (let res_of_e = make_eexpr_of_ast e
-        in let res_of_i1 = make_einstr_of_ast i1
-          in let res_of_i2 = make_einstr_of_ast i2
-            in match res_of_e, res_of_i1, res_of_i2 with 
-            | Error msg, _, _ -> Error msg
-            | _, Error msg, _ -> Error msg
-            | _, _, Error msg -> Error msg
-            | OK exp, OK inst1, OK inst2 -> OK (Iif (exp, inst1, inst2)))
+        make_eexpr_of_ast typ_var typ_fun e >>= fun expr ->
+        type_expr typ_var typ_fun expr >>= fun te ->
+        make_einstr_of_ast typ_var typ_fun i1 >>= fun instr1 ->
+        make_einstr_of_ast typ_var typ_fun i2 >>= fun instr2 ->
+        OK (Iif (expr, instr1, instr2))
     | Node(Twhile, [e; i]) -> 
-      (let res_of_e = make_eexpr_of_ast e
-        in let res_of_i = make_einstr_of_ast i
-          in match res_of_e, res_of_i with 
-          | Error msg, _ -> Error msg
-          | _, Error msg -> Error msg
-          | OK exp, OK inst-> OK (Iwhile (exp, inst)))
-    | Node(Tblock, i_list) -> 
-      (let res_of_i_list = list_map_res make_einstr_of_ast i_list
-        in match res_of_i_list with
-        | Error msg -> Error msg
-        | OK instr_list -> OK (Iblock instr_list))
+        make_eexpr_of_ast typ_var typ_fun e >>= fun expr ->
+        type_expr typ_var typ_fun expr >>= fun te ->
+        make_einstr_of_ast typ_var typ_fun i >>= fun instr ->
+        OK (Iwhile (expr, instr))
+    | Node(Tblock, i_list) ->
+        list_map_res (make_einstr_of_ast typ_var typ_fun) i_list >>= fun instr_list -> 
+        OK (Iblock instr_list)
     | Node(Treturn, [e]) -> 
-      (let res_of_e = make_eexpr_of_ast e 
-        in match res_of_e with 
-        | OK exp -> OK (Ireturn exp)
-        | Error msg -> Error msg)
+        make_eexpr_of_ast typ_var typ_fun e >>= fun expr ->
+        type_expr typ_var typ_fun expr >>= fun te ->
+        OK (Ireturn expr)        
     | Node(Tcall, [StringLeaf f; Node(Targs, args)]) -> 
-      (let res = list_map_res make_eexpr_of_ast args 
-        in match res with
-        | Error msg -> Error msg
-        | OK exprs -> OK (Icall (f, exprs)))
+        list_map_res (make_eexpr_of_ast typ_var typ_fun) args >>= fun exprs ->
+        list_map_res (type_expr typ_var typ_fun) exprs >>= fun types ->
+        (match Hashtbl.find_option typ_fun f with
+        | None -> Error (Format.sprintf "E: Unknown argument types of function %s." f) 
+        | Some (arg_types, ret_type) -> 
+          if types = arg_types
+            then OK (Icall (f, exprs))
+            else Error (Format.sprintf "E: Unvalid argument types in function %s calling." f))
+    | Node (Tdeclare, [TypeLeaf t; StringLeaf s]) ->
+        if t != Tvoid 
+          then 
+            if Hashtbl.mem typ_var s 
+              then 
+                Error (Format.sprintf "E: Variable %s already declared." s)
+              else 
+                (Hashtbl.add typ_var s t;
+                OK (Ideclare (t ,s)))
+          else 
+            Error (Format.sprintf "E: Can not declare void variable.")
     | NullLeaf -> OK (Iblock [])
     | _ -> Error (Printf.sprintf "Unacceptable ast in make_einstr_of_ast %s"
                     (string_of_ast a))
@@ -122,20 +160,22 @@ let rec make_einstr_of_ast (a: tree) : instr res =
   | Error msg -> Error (Format.sprintf "In make_einstr_of_ast %s:\n%s"
                           (string_of_ast a) msg)
 
-let make_ident (a: tree) : string res =
+let make_ident (a: tree) : (string * typ) res =
   match a with
-  | Node (Targ, [s]) ->
-    OK (string_of_stringleaf s)
+  | Node (Targ, [TypeLeaf t; StringLeaf s]) -> OK (s, t)
   | a -> Error (Printf.sprintf "make_ident: unexpected AST: %s"
                   (string_of_ast a))
 
-let make_fundef_of_ast (a: tree) : (string * efun) res =
+let make_fundef_of_ast (typ_fun : (string, typ list * typ) Hashtbl.t) (a: tree) : (string * efun) res =
   match a with
-  | Node (Tfundef, [Node(Tfunname, [StringLeaf fname]); Node (Tfunargs, fargs); Node(Tfunbody, [fbody])]) ->
+  | Node (Tfundef, [Node(Tfuntype, [TypeLeaf t]); Node(Tfunname, [StringLeaf fname]); Node (Tfunargs, fargs); Node(Tfunbody, [fbody])]) ->
     list_map_res make_ident fargs >>= fun fargs ->
-     (* TODO *)
-      make_einstr_of_ast fbody >>= fun fbody ->
-        OK (fname, {funargs = fargs; funbody = fbody})
+      (* TODO *)
+      let typ_var = Hashtbl.of_list fargs
+        in let arg_types = List.map (fun (arg, typ) -> typ) fargs
+          in Hashtbl.add typ_fun fname (arg_types, t);
+          make_einstr_of_ast typ_var typ_fun fbody >>= fun fbody ->
+          OK (fname, {funargs = fargs; funbody = fbody; funvartyp = typ_var; funrettype = t})
   | _ ->
     Error (Printf.sprintf "make_fundef_of_ast: Expected a Tfundef, got %s."
              (string_of_ast a))
@@ -143,7 +183,11 @@ let make_fundef_of_ast (a: tree) : (string * efun) res =
 let make_eprog_of_ast (a: tree) : eprog res =
   match a with
   | Node (Tlistglobdef, l) ->
-    list_map_res (fun a -> make_fundef_of_ast a >>= fun (fname, efun) -> OK (fname, Gfun efun)) l
+    let fun_typ = Hashtbl.create (List.length l) in
+    Hashtbl.replace fun_typ "print" ([Tint], Tvoid);
+    Hashtbl.replace fun_typ "print_int" ([Tint], Tvoid);
+    Hashtbl.replace fun_typ "print_char" ([Tchar], Tvoid);
+    list_map_res (fun a -> make_fundef_of_ast fun_typ a >>= fun (fname, efun) -> OK (fname, Gfun efun)) l
   | _ ->
     Error (Printf.sprintf "make_fundef_of_ast: Expected a Tlistglobdef, got %s."
              (string_of_ast a))
diff --git a/src/elang_print.ml b/src/elang_print.ml
index 8e4d55d111be23ddb39cf66fccb0453657262e4a..c090ed55b3d993cde2ba0f9bdc5c35fd5ab0d3bd 100644
--- a/src/elang_print.ml
+++ b/src/elang_print.ml
@@ -27,7 +27,7 @@ let rec dump_eexpr = function
   | Eint i -> Printf.sprintf "%d" i
   | Evar s -> Printf.sprintf "%s" s
   | Ecall (f, args) -> Printf.sprintf "%s(%s)" f (String.concat ", " (List.map dump_eexpr args))
-
+  | Echar c -> Printf.sprintf "%c" c
 let indent_size = 2
 let spaces n =
   range (indent_size*n) |> List.map (fun _ -> ' ') |> String.of_list
@@ -59,7 +59,9 @@ let rec dump_einstr_rec indent oc i =
   | Icall(f, args) ->
     print_spaces oc indent;
     Format.fprintf oc "%s(%s);\n" f (String.concat ", " (List.map dump_eexpr args))
-
+  | Ideclare(t, s) ->
+    print_spaces oc indent;
+    Format.fprintf oc "%s %s;\n" (string_of_typ t) s
 
 let dump_einstr oc i = dump_einstr_rec 0 oc i
 
@@ -67,7 +69,7 @@ let dump_einstr oc i = dump_einstr_rec 0 oc i
 let dump_efun oc funname {funargs; funbody} =
   Format.fprintf oc "%s(%s) {\n%a\n}\n"
     funname
-    (String.concat "," funargs)
+    (String.concat "," (List.map (fun (s, t) -> Printf.sprintf "%s %s" (string_of_typ t) s) funargs))
     dump_einstr funbody
 
 let dump_eprog oc = dump_prog dump_efun oc
diff --git a/src/elang_run.ml b/src/elang_run.ml
index 4a5bd71713a29230da9cb83f3d4d77635354265e..92b77fb637a6cf4750296b6f2dce21d2d59fd9d6 100644
--- a/src/elang_run.ml
+++ b/src/elang_run.ml
@@ -4,6 +4,10 @@ open Prog
 open Utils
 open Builtins
 
+let remove_local_vars st local_st =
+   let filtered_env = Hashtbl.filteri (fun k v -> if Hashtbl.mem st.env k then (Printf.printf "Not removing %s\n" k; true) else (Printf.printf "removing %s\n" k; false) ) local_st.env
+      in {local_st with env = filtered_env}
+
 let binop_bool_to_int f x y = if f x y then 1 else 0
 
 (* [eval_binop b x y] évalue l'opération binaire [b] sur les arguments [x]
@@ -39,32 +43,19 @@ let rec eval_eexpr oc st (ep: eprog) (e : expr) : (int * int state) res =
       | Some i -> OK (i, st)
       | None -> Error "Variable is not defined")
    | Ebinop (b, ex, ey) -> 
-      (let res_x = eval_eexpr oc st ep ex
-         in match res_x with
-         | Error msg -> Error msg
-         | OK (x, st') -> 
-            let res_y = eval_eexpr oc st' ep ey
-               in match res_y with
-               | Error msg -> Error msg
-               | OK (y, st'') -> OK (eval_binop b x y, st''))
+      eval_eexpr oc st ep ex >>= fun (x, st') ->
+      eval_eexpr oc st' ep ey >>= fun (y, st'') ->
+      OK (eval_binop b x y, st'')
    | Eunop (u, ex) ->
-      (let res_x = eval_eexpr oc st ep ex
-         in match res_x with
-         | Error msg -> Error msg
-         | OK (x, st') -> OK (eval_unop u x, st'))
+      eval_eexpr oc st ep ex >>= fun (x, st') ->
+      OK (eval_unop u x, st')
    | Ecall (f, args) -> 
-      let (res : (int list * int state) res) = List.fold_left (
-            fun (acc : (int list * int state) res) (arg : expr) -> 
-            match acc with
-            | Error msg -> Error msg
-            | OK (l, st') -> 
-               match eval_eexpr oc st' ep arg with
-               | Error msg -> Error msg
-               | OK (i, st'') -> OK ((l@[i]), st'')
-                  ) (OK([], st)) args
-         in match res with
-         | Error msg -> Error msg
-         | OK (int_args, st') -> 
+      (List.fold_left
+            (fun acc arg -> 
+            acc >>= fun (l, st') ->
+            eval_eexpr oc st' ep arg >>= fun (i, st'') ->
+            OK ((l@[i]), st'')) 
+               (OK([], st)) args >>= fun(int_args, st') -> 
             match find_function ep f with
             | OK found_f -> 
                (match eval_efun oc st' ep found_f f int_args with
@@ -75,9 +66,10 @@ let rec eval_eexpr oc st (ep: eprog) (e : expr) : (int * int state) res =
                (match do_builtin oc st'.mem f int_args with
                | Error msg -> Error msg
                | OK None -> Error (Format.sprintf "E: Function %s doesn't have a return value.\n" f)
-               | OK (Some ret) -> OK (ret, st'))
+               | OK (Some ret) -> OK (ret, st')))
+   | Echar c -> OK (Char.code c, st)
          
-(* [eval_einstr oc st ins] évalue l'instrution [ins] en partant de l'état [st].
+(* [eval_einstr oc st ins] évalue l'instruction [ins] en partant de l'état [st].
 
    Le paramètre [oc] est un "output channel", dans lequel la fonction "print"
    écrit sa sortie, au moyen de l'instruction [Format.fprintf].
@@ -92,31 +84,33 @@ let rec eval_eexpr oc st (ep: eprog) (e : expr) : (int * int state) res =
 and eval_einstr oc (st: int state) (ep: eprog) (ins: instr) :
   (int option * int state) res =
    match ins with
-   | Iassign (s, e) -> 
-      (match eval_eexpr oc st ep e with
-         | Error msg -> Error msg
-         | OK (v, st') -> 
-            let replace st s v =
+   | Iassign (s, e) ->
+      if Hashtbl.mem st.env s
+         then    
+            (let replace st s v =
                   let new_env = Hashtbl.copy st.env 
                      in Hashtbl.replace new_env s v; 
-                        {st with env = new_env}  
-               in OK (None, replace st' s v))
+                        {st with env = new_env} 
+               in match eval_eexpr oc st ep e with
+               | Error msg -> Error msg
+               | OK (v, st') -> OK (None, replace st' s v))
+         else
+            Error (Format.sprintf "E: Variable %s was not declared." s)
    | Iif (e, i1, i2) -> 
-      (match eval_eexpr oc st ep e with 
-      | Error msg -> Error msg
-      | OK (v, st') -> if v = 0 then eval_einstr oc st' ep i2 else eval_einstr oc st' ep i1)
+      (eval_eexpr oc st ep e >>= fun (v, st') -> 
+         if v != 0 
+            then eval_einstr oc st' ep i1 >>= fun (r_opt, st'') -> 
+               OK (r_opt, remove_local_vars st' st'') 
+            else eval_einstr oc st' ep i2 >>= fun (r_opt, st'') -> 
+               OK (r_opt, remove_local_vars st' st''))
    | Iwhile (e, i) -> 
-      (match eval_eexpr oc st ep e with
-         | Error msg -> Error msg
-         | OK (v, st') ->
-            if v = 1 
-               then (let res_i = eval_einstr oc st' ep i
-                  in match res_i with
-                  | Error msg -> Error msg
-                  | OK (r_opt, next_st) -> match r_opt with 
-                     | None -> eval_einstr oc next_st ep (Iwhile (e, i))
-                     | Some r -> OK (r_opt, next_st)) 
-               else OK(None, st'))
+      (eval_eexpr oc st ep e >>= fun (v, st') ->
+         if v != 0 
+            then eval_einstr oc st' ep i >>= fun (r_opt, next_st) -> 
+               match r_opt with 
+               | None -> eval_einstr oc (remove_local_vars st' next_st) ep (Iwhile (e, i))
+               | Some r -> OK (r_opt, remove_local_vars st' next_st)
+            else OK (None, st'))
    | Iblock i_list -> 
       (match i_list with
       | [] -> OK (None, st)
@@ -126,31 +120,26 @@ and eval_einstr oc (st: int state) (ep: eprog) (ins: instr) :
          | OK (Some r, next_st) -> OK (Some r, next_st)
          | OK (None, next_st) -> eval_einstr oc next_st ep (Iblock rest))
    | Ireturn e -> 
-      (match eval_eexpr oc st ep e with
-      | Error msg -> Error msg
-      | OK (v, st') -> OK(Some v, st'))  
+      eval_eexpr oc st ep e >>= fun (v, st') -> 
+         OK(Some v, st')
    | Icall (f, args) -> 
-      let (res : (int list * int state) res) = List.fold_left (
-            fun (acc : (int list * int state) res) (arg : expr) -> 
-            match acc with
-            | Error msg -> Error msg
-            | OK (l, st') -> 
-               match eval_eexpr oc st' ep arg with
-               | Error msg -> Error msg
-               | OK (i, st'') -> OK ((l@[i]), st'')
-                  ) (OK([], st)) args
-         in match res with
-         | Error msg -> Error msg
-         | OK (int_args, st') -> 
+      (List.fold_left
+         (fun acc arg -> 
+         acc >>= fun (l, st') ->
+         eval_eexpr oc st' ep arg >>= fun (i, st'') ->
+         OK ((l@[i]), st'')) 
+            (OK([], st)) args >>= fun(int_args, st') -> 
             match find_function ep f with
             | OK found_f -> 
-               (match eval_efun oc st' ep found_f f int_args with
-               | Error msg -> Error msg
-               | OK (_, st'') -> OK (None, st''))
+               (eval_efun oc st' ep found_f f int_args >>= fun (_, st'') -> 
+                  OK (None, st''))
             | Error msg -> 
-               (match do_builtin oc st'.mem f int_args with
-               | OK _ -> OK (None, st')
-               | Error msg -> Error msg )
+               (do_builtin oc st'.mem f int_args >>= fun _ -> 
+                  OK (None, st')))
+   | Ideclare (_, s) -> 
+      let new_env = Hashtbl.copy st.env
+         in Hashtbl.add new_env s 0;
+         OK (None, {st with env = new_env})
 
 (* [eval_efun oc st f fname vargs] évalue la fonction [f] (dont le nom est
    [fname]) en partant de l'état [st], avec les arguments [vargs].
@@ -167,7 +156,7 @@ and eval_efun oc (st: int state) ep ({ funargs; funbody}: efun)
      seulement ses arguments), puis on restore l'environnement de l'appelant. *)
   let env_save = Hashtbl.copy st.env in
   let env = Hashtbl.create 17 in
-  match List.iter2 (fun a v -> Hashtbl.replace env a v) funargs vargs with
+  match List.iter2 (fun (a, t) v -> Hashtbl.replace env a v) funargs vargs with
   | () ->
     eval_einstr oc { st with env } ep funbody >>= fun (v, st') ->
     OK (v, { st' with env = env_save })
diff --git a/src/prog.ml b/src/prog.ml
index 5da26745e8461b83070928a8f3647a567394b2c7..515bbfbfb57586f706fa9b2e82cdcba1fbbbd6fe 100644
--- a/src/prog.ml
+++ b/src/prog.ml
@@ -6,6 +6,17 @@ type mem_access_size =
   | MAS4
   | MAS8
 
+type typ =
+  | Tint 
+  | Tchar
+  | Tvoid
+
+let string_of_typ t =
+  match t with
+  | Tint -> "int"
+  | Tchar -> "char"
+  | Tvoid -> "void"
+
 let string_of_mem_access_size mas =
   match mas with
   | MAS1 -> "{1}"
diff --git a/tests/Makefile b/tests/Makefile
index ef3fa0a92cb0f08481c60752b7797db738cd6921..5dbb6206ac0f9999921b11a2cd79d3d7bf8017ff 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,7 +1,7 @@
 # if make is launched with a DIR variable, pass it as the -f option to test.py
 # 'make DIR=basic/mul*.e' launches all the files starting with mul in the basic directory
 # otherwise, use basic/*.e as a default
-FILES := $(if $(DIR),$(DIR),funcall/*.e)
+FILES := $(if $(DIR),$(DIR),type_basic/*.e)
 
 OPTS := $(if $(OPTS), $(OPTS),)