diff --git a/src/plugins/aorai/Makefile.in b/src/plugins/aorai/Makefile.in
index a816d71fcd56a6f5ab7c3250b2f94e79d66c06b3..c39a616ce7e5ea1bb53d8bbd826cdc308701d539 100644
--- a/src/plugins/aorai/Makefile.in
+++ b/src/plugins/aorai/Makefile.in
@@ -51,6 +51,8 @@ PLUGIN_CMO:= bool3 \
 	path_analysis \
 	promelaoutput \
 	logic_simplification \
+	aorai_graph \
+	aorai_metavariables \
 	data_for_aorai \
 	aorai_utils \
 	ltl_output \
diff --git a/src/plugins/aorai/aorai_dataflow.ml b/src/plugins/aorai/aorai_dataflow.ml
index 554af1f3639ad3531632e0f8dfec0de3e106852b..f6315b5ce509e2b506f61ef0a6446d5d1189eda2 100644
--- a/src/plugins/aorai/aorai_dataflow.ml
+++ b/src/plugins/aorai/aorai_dataflow.ml
@@ -265,7 +265,7 @@ let actions_to_range l =
   in List.fold_left treat_one_action Cil_datatype.Term.Map.empty l
 
 let make_start_transition ?(is_main=false) kf init_states =
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let is_crossable = 
     if is_main then 
       Aorai_utils.isCrossableAtInit 
@@ -303,7 +303,7 @@ let make_start_transition ?(is_main=false) kf init_states =
 let make_return_transition kf state =
   let s = Kernel_function.find_return kf in
   set_return_state s state;
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let treat_one_state state bindings acc =
     let my_trans = Path_analysis.get_transitions_of_state state auto in
     let last = Data_for_aorai.Aorai_state.Set.singleton state in
@@ -624,7 +624,7 @@ let compute_forward () =
   if Data_for_aorai.isIgnoredFunction (Kernel_function.get_name kf) then
     Aorai_option.abort "Main function %a is ignored by Aorai"
       Kernel_function.pretty kf;
-  let (states,_) = Data_for_aorai.getAutomata () in
+  let (states,_) = Data_for_aorai.getGraph () in
   let start = 
     List.fold_left
       (fun acc s ->
@@ -833,7 +833,7 @@ let filter_possible_states kf states =
 
 let filter_return_states kf states =
   let end_state = Return_state.find (Kernel_function.find_return kf) in
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let is_possible_state start_state state _ =
     try
       let trans = Path_analysis.get_transitions_of_state state auto in
diff --git a/src/plugins/aorai/aorai_graph.ml b/src/plugins/aorai/aorai_graph.ml
new file mode 100644
index 0000000000000000000000000000000000000000..9425f061212e66d0e319e2891086ff39ab6ff34d
--- /dev/null
+++ b/src/plugins/aorai/aorai_graph.ml
@@ -0,0 +1,71 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Aorai plug-in of Frama-C.                        *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2018                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*    INRIA (Institut National de Recherche en Informatique et en         *)
+(*           Automatique)                                                 *)
+(*    INSA  (Institut National des Sciences Appliquees)                   *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Promelaast
+
+type state = Promelaast.state
+type transition = (typed_condition * action) trans
+
+module Vertex =
+struct
+  type t = state
+  let compare x y = x.nums - y.nums
+  let hash x = x.nums
+  let equal x y = x.nums = y.nums
+  let default = {
+    nums = -1; name = ""; multi_state = None;
+    acceptation = Bool3.False; init = Bool3.False
+  }
+end
+
+module Edge =
+struct
+  type t = transition
+  let compare x y = x.numt - y.numt
+  let default = {
+    numt = -1; start = Vertex.default; stop = Vertex.default;
+    cross = TTrue,[]
+  }
+end
+
+include Graph.Imperative.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge)
+
+let of_automaton auto =
+  let g = create () in
+  List.iter (fun t -> add_edge_e g (t.start,t,t.stop)) auto.trans;
+  g
+
+let states g =
+  fold_vertex (fun v acc -> v :: acc) g []
+
+let filter_states f g =
+  fold_vertex (fun v acc -> if f v then v :: acc else acc) g []
+
+let init_states g =
+  filter_states (fun v -> v.Promelaast.init = Bool3.True) g
+
+let edges g =
+  fold_edges_e (fun e acc -> e :: acc) g []
+
diff --git a/src/plugins/aorai/aorai_graph.mli b/src/plugins/aorai/aorai_graph.mli
new file mode 100644
index 0000000000000000000000000000000000000000..38d110bb4dba479a48aa7e1ecd1ddb6861344236
--- /dev/null
+++ b/src/plugins/aorai/aorai_graph.mli
@@ -0,0 +1,43 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Aorai plug-in of Frama-C.                        *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2018                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*    INRIA (Institut National de Recherche en Informatique et en         *)
+(*           Automatique)                                                 *)
+(*    INSA  (Institut National des Sciences Appliquees)                   *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+type state = Promelaast.state
+type transition =
+  (Promelaast.typed_condition * Promelaast.action) Promelaast.trans
+type edge = state * transition * state
+
+include Graph.Sig.I
+  with type V.t = state
+   and type V.label = state
+   and type E.t = edge
+   and type E.label = transition
+   and type edge := edge
+
+val of_automaton : Promelaast.typed_automaton -> t
+
+val states : t -> state list
+val init_states : t -> state list
+val edges : t -> edge list
+
diff --git a/src/plugins/aorai/aorai_metavariables.ml b/src/plugins/aorai/aorai_metavariables.ml
new file mode 100644
index 0000000000000000000000000000000000000000..dfcfe026805ca0dbeb3cfb820888ac62bae9e4ea
--- /dev/null
+++ b/src/plugins/aorai/aorai_metavariables.ml
@@ -0,0 +1,143 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Aorai plug-in of Frama-C.                        *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2018                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*    INRIA (Institut National de Recherche en Informatique et en         *)
+(*           Automatique)                                                 *)
+(*    INSA  (Institut National des Sciences Appliquees)                   *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+open Promelaast
+
+
+let dkey_metavar_init = Aorai_option.register_category "metavar-init"
+
+module type InitAnalysisParam =
+sig
+  val is_metavariable : varinfo -> bool
+end
+
+module InitAnalysis (Env : InitAnalysisParam) =
+struct
+  type vertex = Aorai_graph.E.vertex
+  type edge = Aorai_graph.E.t
+  type g = Aorai_graph.t
+
+  module Set = Cil_datatype.Varinfo.Set
+  type data = Bottom | InitializedSet of Set.t
+
+  let dkey = dkey_metavar_init
+
+  let top = InitializedSet Set.empty
+
+  let init v =
+    if v.Promelaast.init = Bool3.True then top else Bottom
+
+  let direction = Graph.Fixpoint.Forward
+
+  let equal d1 d2 =
+    match d1, d2 with
+    | Bottom, d | d, Bottom -> d = Bottom
+    | InitializedSet s1, InitializedSet s2 -> Set.equal s1 s2
+
+  let join d1 d2 =
+    match d1, d2 with
+    | Bottom, d | d, Bottom -> d
+    | InitializedSet s1, InitializedSet s2 ->
+      InitializedSet (Set.inter s1 s2)
+
+  let used_metavariables cond =
+    let result = ref Set.empty in
+    let visit_term =
+      let v = object
+        inherit Visitor.frama_c_inplace
+        method!vlogic_var_use lv =
+          match lv.lv_origin with
+          | Some vi when Env.is_metavariable vi ->
+            result := Set.add vi !result;
+            Cil.SkipChildren
+          | _ -> Cil.SkipChildren
+      end in
+      fun t -> ignore (Visitor.visitFramacTerm v t)
+    in
+    let rec visit_cond = function
+      | TAnd (c1,c2) -> visit_cond c1; visit_cond c2
+      | TOr (c1,c2) -> visit_cond c1; visit_cond c2
+      | TNot (c) -> visit_cond c
+      | TRel (_,t1,t2) -> visit_term t1; visit_term t2
+      | TCall _ | TReturn _ | TTrue | TFalse -> ()
+    in
+    visit_cond cond;
+    !result
+
+  let pretty_state fmt st =
+    Format.pp_print_string fmt st.Promelaast.name
+
+  let pretty_set fmt set =
+    let l = Set.elements set in
+    Pretty_utils.pp_list ~sep:", " Cil_printer.pp_varinfo fmt l
+
+  let _pretty_data fmt = function
+    | Bottom -> Format.printf "Bottom"
+    | InitializedSet set -> pretty_set fmt set
+
+  let alarm (src,_tr,dst) vars =
+    Aorai_option.abort
+      "The metavariables %a may not be initialized before the transition \
+       from %a to %a."
+      pretty_set vars
+      pretty_state src
+      pretty_state dst
+
+  let analyze ((src,tr,dst) as edge) = function
+    | Bottom -> Bottom
+    | InitializedSet initialized ->
+      let cond,act = tr.cross in
+      (* Check that the condition uses only initialized variables *)
+      let used = used_metavariables cond in
+      let diff = Set.diff used initialized in
+      if not (Set.is_empty diff) then
+        alarm edge diff;
+      (* Add variables intialized by the condition *)
+      let add_initialized set = function
+        | Copy_value ((TVar({lv_origin = Some vi}),_),_) -> Set.add vi set
+        | _ -> set
+      in
+      let initialized' = List.fold_left add_initialized initialized act in
+      Aorai_option.debug ~dkey "%a {%a} -> %a {%a}"
+          pretty_state src pretty_set initialized
+          pretty_state dst pretty_set initialized';
+      InitializedSet initialized'
+end
+
+
+let checkInitialization auto =
+  let module P =
+  struct
+    let is_metavariable vi =
+      let module Map = Datatype.String.Map in
+      Map.exists (fun _ vi' -> (vi'.vid = vi.vid)) auto.metavariables
+  end
+  in
+  let module A = InitAnalysis (P) in
+  let module Fixpoint = Graph.Fixpoint.Make (Aorai_graph) (A) in
+  let g = Aorai_graph.of_automaton auto in
+  let _result = Fixpoint.analyze A.init g in
+  ()
diff --git a/src/plugins/aorai/aorai_register.ml b/src/plugins/aorai/aorai_register.ml
index f7a12ad4d258972d402972bab40bf14eb6e6a730..b9ea313fb7207c211f4fdc96b7ae9c54afde0e96 100644
--- a/src/plugins/aorai/aorai_register.ml
+++ b/src/plugins/aorai/aorai_register.ml
@@ -48,7 +48,7 @@ let convert_ltl_exprs t =
         POr(c1,c2) -> POr (convert_cond c1, convert_cond c2)
       | PAnd(c1,c2) -> PAnd(convert_cond c1, convert_cond c2)
       | PNot c -> PNot (convert_cond c)
-      | PCall _ | PReturn _ | PTrue | PFalse | AfVar _ -> cond
+      | PCall _ | PReturn _ | PTrue | PFalse | PAssign _ -> cond
       | PRel(Neq,PVar x,PCst _) ->
         (try
            let (rel,t1,t2) = Hashtbl.find ltl_to_promela x in PRel(rel,t1,t2)
@@ -109,10 +109,10 @@ let load_ya_file f =
 let load_promela_file f  =
   try
     let c = check_and_open_in f "invalid Promela file" in
-    let (s,t) = Promelalexer.parse c  in
-    let t = convert_ltl_exprs t in
+    let auto = Promelalexer.parse c  in
+    let trans = convert_ltl_exprs auto.trans in
     close_in c;
-    Data_for_aorai.setAutomata (s,t);
+    Data_for_aorai.setAutomata { auto with trans };
   with 
   | Promelalexer.Error(loc,msg) -> syntax_error loc msg
 
diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml
index b2c42ef706f776857dc628b11d2b232e40fbb9eb..5daa862d825c943c28f72abd2ccc46b654059d2d 100644
--- a/src/plugins/aorai/aorai_utils.ml
+++ b/src/plugins/aorai/aorai_utils.ml
@@ -896,7 +896,7 @@ let mk_global_comment txt = mk_global (GText (txt))
 (** {b Initialization management / computation} *)
 
 let mk_global_states_init root =
-  let (states,_ as auto) = Data_for_aorai.getAutomata () in
+  let (states,_ as auto) = Data_for_aorai.getGraph () in
   let states = List.sort Data_for_aorai.Aorai_state.compare states in
   let is_possible_init state =
     state.Promelaast.init = Bool3.True &&
@@ -1049,7 +1049,7 @@ let pred_of_condition subst subst_res label cond =
   snd (aux None true cond)
 
 let mk_deterministic_lemma () =
-  let automaton = Data_for_aorai.getAutomata () in
+  let automaton = Data_for_aorai.getGraph () in
   let make_one_lemma state =
     let label = Cil_types.FormalLabel "L" in
     let disjoint_guards acc trans1 trans2 =
@@ -1092,7 +1092,7 @@ let mk_deterministic_lemma () =
   List.iter make_one_lemma (fst automaton)
 
 let make_enum_states () =
-  let state_list =fst (Data_for_aorai.getAutomata()) in
+  let state_list =fst (Data_for_aorai.getGraph()) in
   let state_list =
     List.map (fun x -> (x.Promelaast.name, x.Promelaast.nums)) state_list
   in
@@ -1122,7 +1122,7 @@ let make_enum_states () =
 
 let getInitialState () =
   let loc = Cil_datatype.Location.unknown in
-  let states = fst (Data_for_aorai.getAutomata()) in
+  let states = fst (Data_for_aorai.getGraph()) in
   let s = List.find (fun x -> x.Promelaast.init = Bool3.True) states in
   Cil.new_exp ~loc (Const (CEnum (find_enum s.nums)))
 
@@ -1165,11 +1165,12 @@ let initGlobals root complete =
   mk_global_comment "//*";
   List.iter mk_global_var (Data_for_aorai.aux_variables());
 
+  let auto = Data_for_aorai.getAutomata () in
   mk_global_comment "//* ";
   mk_global_comment "//****************** ";
   mk_global_comment "//* Metavariables";
   mk_global_comment "//*";
-  Datatype.String.Map.iter (fun _ -> mk_global_var) !Data_for_aorai.global_table;
+  Datatype.String.Map.iter (fun _ -> mk_global_var) auto.metavariables;
 
   if Aorai_option.Deterministic.get () then begin
     (* must flush now previous globals which are used in the lemmas in order to
@@ -1209,7 +1210,7 @@ let automaton_locations loc =
            Logic_const.new_identified_term
              (Logic_const.tvar
                 (Data_for_aorai.get_state_logic_var state)), FromAny)
-        (fst (Data_for_aorai.getAutomata()))
+        (fst (Data_for_aorai.getGraph()))
   in
   (Logic_const.new_identified_term
      (Logic_const.tvar ~loc
@@ -1333,7 +1334,7 @@ let get_reachable_trans_to state st auto current_state =
 (* force that we have a crossable transition for each state in which the
    automaton might be at current event. *)
 let force_transition loc f st current_state =
-  let (states, _ as auto) = Data_for_aorai.getAutomata () in
+  let (states, _ as auto) = Data_for_aorai.getGraph () in
   (* We iterate aux on all the states, to get
      - the predicate indicating in which states the automaton cannot possibly
        be before the transition (because we can't fire a transition from there).
@@ -1456,7 +1457,7 @@ forces that parent states of a state with action are mutually exclusive,
 at least at pebble level.
 *)
 let incompatible_states loc st current_state =
-  let (states,_ as auto) = Data_for_aorai.getAutomata () in
+  let (states,_ as auto) = Data_for_aorai.getGraph () in
   let aux precond state =
     let trans = get_reachable_trans_to state st auto current_state in
     let actions = partition_action trans in
@@ -1834,7 +1835,7 @@ let auto_func_behaviors loc f st state =
   in
   Aorai_option.debug
     "func behavior for %a (%s)" Kernel_function.pretty f call_or_ret;
-  let (states, _) as auto = Data_for_aorai.getAutomata() in
+  let (states, _) as auto = Data_for_aorai.getGraph() in
   let requires = auto_func_preconditions loc f st state in
   let post_cond =
     let called_pre =
@@ -1983,7 +1984,7 @@ let auto_func_block generated_kf loc f st status res =
   in
   Aorai_option.debug
     ~dkey "func code for %a (%s)" Kernel_function.pretty f call_or_ret;
-  let (states, _) as auto = Data_for_aorai.getAutomata() in
+  let (states, _) as auto = Data_for_aorai.getGraph() in
 
   (* For the following tests, we need a copy of every state. *)
 
@@ -2077,7 +2078,7 @@ let auto_func_block generated_kf loc f st status res =
   new_funcs,res_block,local_var
 
 let get_preds_wrt_params_reachable_states state f status =
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let treat_one_trans acc tr = Logic_simplification.tor acc (fst tr.cross) in
   let find_trans state prev tr =
     Path_analysis.get_edges prev state auto @ tr
diff --git a/src/plugins/aorai/aorai_visitors.ml b/src/plugins/aorai/aorai_visitors.ml
index a0d12c2dc3e0d065997f9da436a1133bfefce998..ad68e06ec7a814d0195d322274e4e352366f3f2c 100644
--- a/src/plugins/aorai/aorai_visitors.ml
+++ b/src/plugins/aorai/aorai_visitors.ml
@@ -33,7 +33,7 @@ open Cil
 let dkey = Aorai_option.register_category "action"
 
 let get_acceptance_pred () =
-  let (st,_) = Data_for_aorai.getAutomata () in
+  let (st,_) = Data_for_aorai.getGraph () in
   List.fold_left
     (fun acc s ->
        match s.acceptation with
@@ -371,14 +371,14 @@ let pred_reachable reachable_states =
       (nb, reachable,
        Logic_const.pand (unreachable, Aorai_utils.is_out_of_state_pred state))
   in
-  let (states,_) = Data_for_aorai.getAutomata () in
+  let (states,_) = Data_for_aorai.getGraph () in
   let (nb, reachable, unreachable) =
     List.fold_left treat_one_state (0,pfalse,ptrue) states
   in
   (nb > 1, reachable, unreachable)
 
 let possible_start kf (start,int) =
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let trans = Path_analysis.get_edges start int auto in
   let treat_one_trans cond tr =
     Logic_const.por
@@ -388,7 +388,7 @@ let possible_start kf (start,int) =
   Logic_const.pand (Aorai_utils.is_state_pred start, cond)
 
 let neg_trans kf trans =
-  let auto = Data_for_aorai.getAutomata () in
+  let auto = Data_for_aorai.getGraph () in
   let rec aux l acc =
     match l with
     | [] -> acc
@@ -527,7 +527,7 @@ class visit_adding_pre_post_from_buch treatloops =
         predicate_to_invariant kf stmt pred
       end
     in
-    let (states,_) = Data_for_aorai.getAutomata () in
+    let (states,_) = Data_for_aorai.getGraph () in
     List.iter treat_one_state states;
     if has_multiple_choice then begin
       let add_possible_state state _ acc =
@@ -584,7 +584,7 @@ class visit_adding_pre_post_from_buch treatloops =
     Data_for_aorai.Aorai_state.Map.fold treat_one_state possible_states []
   in
   let partition_pre_state map =
-    let (states,_) = Data_for_aorai.getAutomata () in
+    let (states,_) = Data_for_aorai.getGraph () in
     let is_equiv st1 st2 =
       let check_one _ o1 o2 =
         match o1, o2 with
@@ -840,7 +840,7 @@ class visit_adding_pre_post_from_buch treatloops =
               in
               (i+1,bhv :: bhvs)
           in
-          let (states,_) = Data_for_aorai.getAutomata () in
+          let (states,_) = Data_for_aorai.getGraph () in
           List.rev (snd (List.fold_left aux (0,bhvs) states))
         end
     in
diff --git a/src/plugins/aorai/data_for_aorai.ml b/src/plugins/aorai/data_for_aorai.ml
index a29a1f62c0cbb1c6cc71a72e170a830a5eae5033..1c9122c284cbec3ba4699d8653bc7b9ee883e10c 100644
--- a/src/plugins/aorai/data_for_aorai.ml
+++ b/src/plugins/aorai/data_for_aorai.ml
@@ -129,14 +129,14 @@ let pnot t =
 
 let rec is_same_expression e1 e2 =
   match e1,e2 with
-    | AVar x, AVar y -> x = y
-    | AVar _,_ | _,AVar _ -> false
     | PVar x, PVar y -> x = y
     | PVar _,_ | _,PVar _ -> false
     | PCst cst1, PCst cst2 -> Logic_utils.is_same_pconstant cst1 cst2
     | PCst _,_ | _,PCst _ -> false
     | PPrm (f1,x1), PPrm(f2,x2) -> f1 = x1 && f2 = x2
     | PPrm _,_ | _,PPrm _ -> false
+    | PMetavar x, PMetavar y -> x = y
+    | PMetavar _,_ | _,PMetavar _ -> false
     | PBinop(b1,l1,r1), PBinop(b2,l2,r2) ->
       b1 = b2 && is_same_expression l1 l2 && is_same_expression r1 r2
     | PBinop _, _ | _, PBinop _ -> false
@@ -207,147 +207,7 @@ let buch_sync   = "Aorai_Sync"                           (* Deprecated ? *)
 
 (* ************************************************************************* *)
 (* Buchi automata as stored after parsing *)
-let automata = ref ([],[])
-
-
-type table = varinfo Datatype.String.Map.t
-
-let global_table = ref Datatype.String.Map.empty (*mettre dans .mli*)
-
-
-module Automaton_graph =
-struct
-  let dummy_vertex = List.hd (Aorai_state.reprs)
-
-  module Vertex =
-  struct
-    type t = Promelaast.state
-    let compare x y = x.nums - y.nums
-    let hash x = x.nums
-    let equal x y = x.nums = y.nums
-  end
-
-  module Edge =
-  struct
-    type t = (Promelaast.typed_condition * Promelaast.action) Promelaast.trans
-    let compare x y = x.numt - y.numt
-    let default =
-      {numt = -1; start = dummy_vertex; stop = dummy_vertex; cross = TTrue,[]}
-  end
-
-  include Graph.Imperative.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge)
-
-  let of_automaton (_,transitions) =
-    let g = create () in
-    List.iter (fun t -> add_edge_e g (t.start,t,t.stop)) transitions;
-    g
-end
-
-let dkey_metavar_init = Aorai_option.register_category "metavar-init"
-
-let checkVariableInitialization auto =
-  let module A =
-  struct
-    type vertex = Automaton_graph.E.vertex
-    type edge = Automaton_graph.E.t
-    type g = Automaton_graph.t
-
-    module Set = Cil_datatype.Varinfo.Set
-    type data = Bottom | InitializedSet of Set.t
-
-    let top = InitializedSet Set.empty
-
-    let direction = Graph.Fixpoint.Forward
-
-    let equal d1 d2 =
-      match d1, d2 with
-      | Bottom, d | d, Bottom -> d = Bottom
-      | InitializedSet s1, InitializedSet s2 -> Set.equal s1 s2
-
-    let join d1 d2 =
-      match d1, d2 with
-      | Bottom, d | d, Bottom -> d
-      | InitializedSet s1, InitializedSet s2 ->
-        InitializedSet (Set.inter s1 s2)
-
-    let used_metavariables cond =
-      let result = ref Set.empty in
-      let visit_term =
-        let v = object
-          inherit Visitor.frama_c_inplace
-          method!vlogic_var_use lv =
-            match lv.lv_origin with
-            | None -> Cil.SkipChildren
-            | Some vi ->
-              let module Map = Datatype.String.Map in
-              if Map.exists (fun _ vi' -> (vi'.vid = vi.vid)) !global_table then
-                result := Set.add vi !result;
-              Cil.SkipChildren
-        end in
-        fun t -> ignore (Visitor.visitFramacTerm v t)
-      in
-      let rec visit_cond =
-        function
-        | TAnd (c1,c2) -> visit_cond c1; visit_cond c2
-        | TOr (c1,c2) -> visit_cond c1; visit_cond c2
-        | TNot (c) -> visit_cond c
-        | TRel (_,t1,t2) -> visit_term t1; visit_term t2
-        | TCall _ | TReturn _ | TTrue | TFalse -> ()
-      in
-      visit_cond cond;
-      !result
-
-    let pretty_state fmt st =
-      Format.pp_print_string fmt st.name
-
-    let pretty_set fmt set =
-      let l = Set.elements set in
-      Pretty_utils.pp_list ~sep:", " Cil_printer.pp_varinfo fmt l
-
-    let _pretty_data fmt = function
-      | Bottom -> Format.printf "Bottom"
-      | InitializedSet set -> pretty_set fmt set
-
-    let alarm (src,_trans,dst) vars =
-      Aorai_option.abort
-        "The metavariables %a may not be initialized before the transition \
-         from %a to %a."
-        pretty_set vars
-        pretty_state src
-        pretty_state dst
-
-    let analyze ((src,trans,dst) as edge) = function
-      | Bottom -> Bottom
-      | InitializedSet initialized ->
-        let cond,act = trans.cross in
-        (* Check that the condition uses only initialized variables *)
-        let used = used_metavariables cond in
-        let diff = Set.diff used initialized in
-        if not (Set.is_empty diff) then
-          alarm edge diff;
-        (* Add variables intialized by the condition *)
-        let add_initialized set = function
-          | Copy_value ((TVar({lv_origin = Some vi}),_),_) -> Set.add vi set
-          | _ -> set
-        in
-        let initialized' = List.fold_left add_initialized initialized act in
-        Aorai_option.debug ~dkey:dkey_metavar_init "%a {%a} -> %a {%a}"
-            pretty_state src pretty_set initialized
-            pretty_state dst pretty_set initialized';
-        InitializedSet initialized'
-  end
-  in
-  let module Initialization = Graph.Fixpoint.Make (Automaton_graph) (A) in
-  let g = Automaton_graph.of_automaton auto in
-  let init_states = Path_analysis.get_init_states auto in
-  let init_data v =
-    if List.exists (fun st -> st.nums = v.nums) init_states (* TODO: use sets *)
-    then A.top
-    else A.Bottom
-  in
-  let _result = Initialization.analyze init_data g in
-  ()
-
+let automata = ref None
 
 (* Each transition with a parametrized cross condition (call param access or return value access) has its parametrized part stored in this array. *)
 let cond_of_parametrizedTransitions = ref (Array.make (1) [[]])
@@ -360,13 +220,24 @@ let functions_from_c = ref []
 let ignored_functions = ref []
 
 (** Return the buchi automata as stored after parsing *)
-let getAutomata () = !automata
+let getAutomata () =
+  match !automata with
+  | Some auto -> auto
+  | None ->
+    Aorai_option.fatal "The automaton has not been compiled yet"
+
+let getGraph () =
+  let auto = getAutomata () in
+  auto.states, auto.trans
 
 (** Return the number of transitions of the automata *)
-let getNumberOfTransitions () = List.length (snd !automata)
+let getNumberOfTransitions () =
+  List.length (getAutomata ()).trans
 
 (** Return the number of states of the automata *)
-let getNumberOfStates () = List.length (fst !automata)
+let getNumberOfStates () =
+  List.length (getAutomata ()).states
+
 
 let is_c_global name =
   try ignore (Globals.Vars.find_from_astinfo name VGlobal); true
@@ -487,7 +358,7 @@ let new_trans start stop cond =
   { start = start; stop = stop; cross = cond; numt = TransIndex.next () }
 
 let check_states s =
-  let states,trans = getAutomata() in
+  let {states;trans} = getAutomata() in
   let max = getNumberOfStates () in
   List.iter
     (fun x -> if x.nums >= max then
@@ -565,17 +436,14 @@ type current_event =
               repr of the stack does not take into account
               this particular event. *)
 
-(*New definition of environment to be able to handle metavariable*)
-type env = { event:current_event list ; var:table}
-
 let add_current_event event env cond =
   let is_empty tbl = Cil_datatype.Varinfo.Hashtbl.length tbl = 0 in
-  match env.event with
+  match env with
       [] -> assert false
     | old_event :: tl ->
       match event, old_event with
         | ENone, _ -> env, cond
-        | _, ENone -> {env with event = event::tl}, cond
+        | _, ENone -> event::tl, cond
         | ECall (kf1,_,_), ECall (kf2,_,_)
           when Kernel_function.equal kf1 kf2 -> env, cond
         | ECall (kf1,tbl1,_), ECall (kf2,tbl2,_)->
@@ -584,15 +452,15 @@ let add_current_event event env cond =
              an empty event. If this situation occurs in an handwritten
              automaton that uses formals we simply reject it.
            *)
-          if is_empty tbl1 && is_empty tbl2 then {env with event = ENone::tl}, TFalse
+          if is_empty tbl1 && is_empty tbl2 then ENone::tl, TFalse
           else
             Aorai_option.abort
               "specification is inconsistent: two call events for distinct \
                functions %a and %a at the same time."
               Kernel_function.pretty kf1 Kernel_function.pretty kf2
-        | ECall (_,_,_), EMulti -> { env with event = event::tl }, cond
+        | ECall (_,_,_), EMulti -> event::tl, cond
         | ECall (kf1,tbl1,_), EReturn kf2 ->
-          if is_empty tbl1 then {env with event = ENone::tl}, TFalse
+          if is_empty tbl1 then ENone::tl, TFalse
           else
             Aorai_option.abort
               "specification is inconsistent: trying to call %a and \
@@ -600,62 +468,62 @@ let add_current_event event env cond =
               Kernel_function.pretty kf1 Kernel_function.pretty kf2
         | ECall(kf1,_,_), ECOR kf2
           when Kernel_function.equal kf1 kf2 ->
-          {env with event = event::tl}, cond
+          event::tl, cond
         | ECall (kf1,tbl1,_), ECOR kf2 ->
-          if is_empty tbl1 then {env with event = ENone::tl}, TFalse
+          if is_empty tbl1 then ENone::tl, TFalse
           else
             Aorai_option.abort
               "specification is inconsistent: trying to call %a and \
                call or return from %a at the same time."
               Kernel_function.pretty kf1 Kernel_function.pretty kf2
         | EReturn kf1, ECall(kf2,tbl2,_) ->
-          if is_empty tbl2 then {env with event = ENone::tl}, TFalse
+          if is_empty tbl2 then ENone::tl, TFalse
           else
             Aorai_option.abort
               "specification is inconsistent: trying to call %a and \
                return from %a at the same time."
             Kernel_function.pretty kf2 Kernel_function.pretty kf1
         | EReturn kf1, (ECOR kf2 | EReturn kf2)
-          when Kernel_function.equal kf1 kf2 -> {env with event = event::tl}, cond
-        | EReturn _, EReturn _ -> {env with event = ENone::tl} , TFalse
-        | EReturn _, ECOR _ -> {env with event = ENone::tl}, TFalse
-        | EReturn _, EMulti -> {env with event = ENone::tl}, TFalse
+          when Kernel_function.equal kf1 kf2 -> event::tl, cond
+        | EReturn _, EReturn _ -> ENone::tl, TFalse
+        | EReturn _, ECOR _ -> ENone::tl, TFalse
+        | EReturn _, EMulti -> ENone::tl, TFalse
         | (EMulti | ECOR _), _ -> assert false
           (* These are compound event. They cannot be found as individual ones*)
 
 let merge_current_event env1 env2 cond1 cond2 =
-  assert (List.tl (env1.event) == List.tl (env2.event));
-  let old_env = List.tl (env2.event) in
-  match (List.hd (env1.event), List.hd (env2.event)) with
+  assert (List.tl env1 == List.tl env2);
+  let old_env = List.tl env2 in
+  match List.hd env1, List.hd env2 with
       | ENone, _ -> env2, tor cond1 cond2
       | _, ENone -> env1, tor cond1 cond2
       | ECall(kf1,_,_), ECall(kf2,_,_)
         when Kernel_function.equal kf1 kf2 -> env2, tor cond1 cond2
-      | ECall _, ECall _ -> { env2 with event = EMulti::old_env}, tor cond1 cond2
+      | ECall _, ECall _ -> EMulti::old_env, tor cond1 cond2
       | ECall _, EMulti -> env2, tor cond1 cond2
       | ECall (kf1,_,_), ECOR kf2 when Kernel_function.equal kf1 kf2 ->
         env2, tor cond1 cond2
       | ECall (kf1,_,_), EReturn kf2 when Kernel_function.equal kf1 kf2 ->
-        { env2 with event = ECOR kf1 :: old_env }, tor cond1 cond2
-      | ECall _, (ECOR _ | EReturn _) -> { env2 with event =  (EMulti :: old_env) }, tor cond1 cond2
+        ECOR kf1 :: old_env, tor cond1 cond2
+      | ECall _, (ECOR _ | EReturn _) -> EMulti :: old_env, tor cond1 cond2
       | EReturn kf1, ECall (kf2,_,_) when Kernel_function.equal kf1 kf2 ->
-        { env2 with event = ECOR kf1 :: old_env }, tor cond1 cond2
-      | EReturn _, ECall _  -> { env2 with event = EMulti :: old_env }, tor cond1 cond2
+        ECOR kf1 :: old_env, tor cond1 cond2
+      | EReturn _, ECall _  -> EMulti :: old_env, tor cond1 cond2
       | EReturn kf1, EReturn kf2 when Kernel_function.equal kf1 kf2 ->
         env2, tor cond1 cond2
-      | EReturn _, EReturn _ -> { env2 with event = EMulti :: old_env }, tor cond1 cond2
+      | EReturn _, EReturn _ -> EMulti :: old_env, tor cond1 cond2
       | EReturn _, EMulti -> env2, tor cond1 cond2
       | EReturn kf1, ECOR kf2 when Kernel_function.equal kf1 kf2 ->
         env2, tor cond1 cond2
       | EReturn _, ECOR _ ->
-        { env2 with event = EMulti :: old_env }, tor cond1 cond2
+        EMulti :: old_env, tor cond1 cond2
       | ECOR kf1, (ECall(kf2,_,_) | EReturn kf2 | ECOR kf2)
         when Kernel_function.equal kf1 kf2 -> env1, tor cond1 cond2
       | ECOR _, (ECall _ | EReturn _ | ECOR _) ->
-        { env2 with event = EMulti :: old_env }, tor cond1 cond2
+        EMulti :: old_env, tor cond1 cond2
       | ECOR _, EMulti -> env2, tor cond1 cond2
       | EMulti, (ECall _ | EReturn _ | ECOR _) -> env1, tor cond1 cond2
-      | EMulti, EMulti -> { env2 with event =  EMulti::old_env }, tor cond1 cond2
+      | EMulti, EMulti -> EMulti::old_env, tor cond1 cond2
 
 let get_bindings st my_var =
   let my_lval = TVar my_var, TNoOffset in
@@ -714,15 +582,15 @@ let check_one top info counter s =
     | ECOR _ | EReturn _ | EMulti | ENone -> None
 
 
-let find_metavar s env =
+let find_metavar s metaenv =
   try
-    Datatype.String.Map.find s (env.var)
+    Datatype.String.Map.find s metaenv
   with Not_found ->
     Aorai_option.abort "Metavariable %s not declared" s
 
 let find_in_env env counter s =
   let current, stack =
-    match env.event with
+    match env with
       | current::stack -> current, stack
       | [] -> Aorai_option.fatal "Empty type-checking environment"
   in
@@ -795,7 +663,7 @@ let find_prm_in_env env ?tr counter f x =
              it in an aux variable or array here.
            *)
           env, Logic_const.tvar (Cil.cvar_to_lvar vi), cond
-    in treat_env true env.event
+    in treat_env true env
   end
 
 module C_logic_env =
@@ -834,17 +702,17 @@ end
 
 module LTyping = Logic_typing.Make(C_logic_env)
 
-let type_expr env ?tr ?current e =
+let type_expr metaenv env ?tr ?current e =
   let loc = Cil_datatype.Location.unknown in
   let rec aux env cond e =
     match e with
       | PVar s ->
         let var = find_in_env env current s in
         env, var, cond
-      | AVar s ->
-        let var = Logic_const.tvar (Cil.cvar_to_lvar (find_metavar s env)) in
-        env, var, cond
       | PPrm(f,x) -> find_prm_in_env env ?tr current f x
+      | PMetavar s ->
+        let var = Logic_const.tvar (Cil.cvar_to_lvar (find_metavar s metaenv)) in
+        env, var, cond
       | PCst (Logic_ptree.IntConstant s) ->
         let e = Cil.parseIntLogic ~loc s in
         env, e, cond
@@ -1024,22 +892,22 @@ let type_expr env ?tr ?current e =
   in
   aux env TTrue e
 
-let type_cond needs_pebble env tr cond =
+let type_cond needs_pebble metaenv env tr cond =
   let current = if needs_pebble then Some tr.stop else None in
   let rec aux pos env =
     function
-      | AfVar (s, e) ->
+      | PAssign (s, e) ->
         if not pos then
           Aorai_option.abort
             "Metavariable assignment cannot be done under a negation";
-        let vi = Datatype.String.Map.find s !global_table in
-        let env, e, c = type_expr env ~tr ?current e in
+        let vi = find_metavar s metaenv in
+        let env, e, c = type_expr metaenv env ~tr ?current e in
         let assign = Copy_value ((TVar (Cil.cvar_to_lvar vi), TNoOffset), e) in
         (* TODO: check type assignability *)
         env, c, [assign]
       | PRel(rel,e1,e2) ->
-        let env, e1, c1 = type_expr env ~tr ?current e1 in
-        let env, e2, c2 = type_expr env ~tr ?current e2 in
+        let env, e1, c1 = type_expr metaenv env ~tr ?current e1 in
+        let env, e2, c2 = type_expr metaenv env ~tr ?current e2 in
         let call_cond = if pos then tand c1 c2 else tor (tnot c1) (tnot c2) in
         let rel = TRel(Logic_typing.type_rel rel,e1,e2) in
         let cond = if pos then tand call_cond rel else tor call_cond rel in
@@ -1093,7 +961,7 @@ let type_cond needs_pebble env tr cond =
         else
           env, TReturn kf, []
   in
-  aux true {env with event = ENone::env.event} cond
+  aux true (ENone::env) cond
 
 module Reject_state =
   State_builder.Option_ref(Aorai_state)
@@ -1113,7 +981,7 @@ let add_if_needed states st =
   then st::states
   else states
 
-let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
+let rec type_seq default_state tr metaenv env needs_pebble curr_start curr_end seq =
   let loc = Cil_datatype.Location.unknown in
   match seq with
     | [] -> (* We identify start and end. *)
@@ -1166,7 +1034,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
         if is_opt then TTrue
         else
           let e = Extlib.the elt.min_rep in
-          let _,e,_ = type_expr env ?current e in
+          let _,e,_ = type_expr metaenv env ?current e in
           (* If we have done at least the lower bound of cycles, we can exit
              the loop. *)
           TRel(Cil_types.Rle,e,counter)
@@ -1181,7 +1049,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
             let e = Logic_const.tint ~loc i in
             TRel(Cil_types.Rlt, counter, e)
           | Some e ->
-            let _,e,_ = type_expr env ?current e in
+            let _,e,_ = type_expr metaenv env ?current e in
             Max_value_counter.replace counter e;
             (* The counter is incremented after the test: it
                must be strictly less than the upper bound to enter
@@ -1195,7 +1063,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
             assert (elt.nested <> []);
             (* we don't have a completely empty condition. *)
             type_seq
-              default_state tr env needs_pebble curr_start my_end elt.nested
+              default_state tr metaenv env needs_pebble curr_start my_end elt.nested
           | Some cond ->
             let seq_start =
               match elt.nested with
@@ -1205,7 +1073,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
             let trans_start = new_trans curr_start seq_start (Normal (TTrue,[]))
             in
             let inner_env, cond, act =
-              type_cond needs_pebble env trans_start cond
+              type_cond needs_pebble metaenv env trans_start cond
             in
             let (env,states, seq_transitions, seq_end) =
               match elt.nested with
@@ -1214,7 +1082,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
                   let intermediate = new_intermediate_state () in
                   let (env, states, transitions, _, seq_end) =
                     type_seq
-                      default_state tr
+                      default_state tr metaenv
                       inner_env needs_pebble seq_start intermediate elt.nested
                   in env, states, transitions, seq_end
             in
@@ -1227,12 +1095,12 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
                   Aorai_option.fatal
                     "Transition guard translated as epsilon transition");
             let states = add_if_needed states seq_start in
-            (match env.event with
+            (match env with
               | [] | (ENone | ECall _) :: _ ->
                 (env, states, transitions, curr_start, seq_end)
               | EReturn kf1 :: ECall (kf2,_,_) :: tl
                   when Kernel_function.equal kf1 kf2 ->
-                {env with event = tl}, states, transitions, curr_start, seq_end
+                  tl, states, transitions, curr_start, seq_end
               | (EReturn _ | ECOR _ ) :: _ ->
                     (* If there is as mismatch (e.g. Call f; Return g), it will
                        be caught later. There are legitimate situations for
@@ -1241,12 +1109,12 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
                      *)
                 (env, states, transitions, curr_start, seq_end)
               | EMulti :: env_tmp ->
-                {env with event = env_tmp}, states, transitions, curr_start, seq_end)
+                env_tmp, states, transitions, curr_start, seq_end)
       in
       let loop_end = if has_loop then new_intermediate_state () else inner_end
       in
       let (_,oth_states,oth_trans,oth_start,_) =
-        type_seq default_state tr env needs_pebble loop_end curr_end seq
+        type_seq default_state tr metaenv env needs_pebble loop_end curr_end seq
       in
       let trans = inner_trans @ oth_trans in
       let states = List.fold_left add_if_needed oth_states inner_states in
@@ -1348,7 +1216,7 @@ let rec type_seq default_state tr env needs_pebble curr_start curr_end seq =
                       if needs_pebble then Some curr_start else None
                     in
                     let _,t,_ =
-                      type_expr env ?current (Extlib.the elt.min_rep)
+                      type_expr metaenv env ?current (Extlib.the elt.min_rep)
                     in
                     TRel (Cil_types.Req, t, Logic_const.tinteger ~loc 0)
                 in
@@ -1432,7 +1300,7 @@ let find_otherwise_trans auto st =
   try let tr = List.find (fun x -> x.cross = Otherwise) trans in Some tr.stop
   with Not_found -> None
 
-let type_trans auto env tr =
+let type_trans auto metaenv env tr =
   let needs_pebble = not (single_path auto tr) in
   let has_siblings =
     match Path_analysis.get_transitions_of_state tr.start auto with
@@ -1449,7 +1317,7 @@ let type_trans auto env tr =
       let default_state = find_otherwise_trans auto tr.start in
       let has_default_state = Extlib.has_some default_state in
       let _,states, transitions,_,_ =
-        type_seq has_default_state tr env needs_pebble tr.start tr.stop seq
+        type_seq has_default_state tr metaenv env needs_pebble tr.start tr.stop seq
       in
       let (states, transitions) =
         if List.exists (fun st -> st.multi_state <> None) states then begin
@@ -1592,13 +1460,16 @@ let add_default_trans (states, transitions as auto) otherwise =
   let transitions = List.fold_left add_one_trans transitions otherwise in
   states, transitions
 
-let type_cond_auto (st,tr as auto) =
-  let otherwise = List.filter (fun t -> t.cross = Otherwise) tr in
+let type_cond_auto auto =
+  let original_auto = auto in
+  let otherwise = List.filter (fun t -> t.cross = Otherwise) auto.trans in
   let add_if_needed acc st =
     if List.memq st acc then acc else st::acc
   in
   let type_trans (states,transitions,add_reject) tr =
-    let (intermediate_states, trans, needs_reject) = type_trans auto {event = []; var = !global_table } tr in (*TODO*)
+    let (intermediate_states, trans, needs_reject) =
+      type_trans (auto.states,auto.trans) auto.metavariables [] tr
+    in
     Aorai_option.debug
       "Considering parsed transition %s -> %s" tr.start.name tr.stop.name;
     Aorai_option.debug
@@ -1621,7 +1492,7 @@ let type_cond_auto (st,tr as auto) =
      add_reject)
   in
   let (states, trans, add_reject) =
-    List.fold_left type_trans (st,[],[]) tr
+    List.fold_left type_trans (auto.states,[],[]) auto.trans
   in
   let auto = propagate_epsilon_transitions (states, trans) in
   let auto = add_reject_trans auto add_reject in
@@ -1630,12 +1501,13 @@ let type_cond_auto (st,tr as auto) =
      must ensure that we use consecutive numbers starting from 0, or we'll
      have needlessly long arrays.
    *)
-  let (states, transitions as auto) =
+  let states, trans =
     match Reject_state.get_option () with
       | Some state ->
           (states, (new_trans state state (TTrue,[])):: transitions)
       | None -> auto
   in
+  let auto = { original_auto with states ; trans } in
   if Aorai_option.debug_atleast 1 then
     Promelaoutput.output_dot_automata auto "aorai_debug_typed.dot";
   let (_,trans) =
@@ -1646,7 +1518,7 @@ let type_cond_auto (st,tr as auto) =
         in match cond with
             TFalse -> acc
           | _ -> (i+1,{ t with cross = (cond,action); numt = i } :: l))
-      (0,[]) transitions
+      (0,[]) trans
   in
   let _, states =
     List.fold_left
@@ -1661,13 +1533,14 @@ let type_cond_auto (st,tr as auto) =
         end else acc)
       (0,[]) states
   in
-   (List.rev states, List.rev trans)
+    { original_auto with states = List.rev states; trans = List.rev trans }
+
 
 (** Stores the buchi automaton and its variables and
     functions as it is returned by the parsing *)
 let setAutomata auto =
   let auto = type_cond_auto auto in
-  automata:=auto;
+  automata:=Some auto;
   check_states "typed automata";
   if Aorai_option.debug_atleast 1 then
     Promelaoutput.output_dot_automata auto "aorai_debug_reduced.dot";
@@ -1677,14 +1550,16 @@ let setAutomata auto =
     (* all transitions have a true parameterized guard, i.e. [[]] *)
     cond_of_parametrizedTransitions :=
       Array.make (getNumberOfTransitions  ()) [[]] ;
-  checkVariableInitialization auto
+  Aorai_metavariables.checkInitialization auto
 
-let getState num = List.find (fun st -> st.nums = num) (fst !automata)
+let getState num =
+  List.find (fun st -> st.nums = num) (getAutomata ()).states
 
-let getStateName num = (getState num).name
+let getStateName num =
+  (getState num).name
 
 let getTransition num =
-  List.find (fun trans -> trans.numt = num) (snd !automata)
+  List.find (fun trans -> trans.numt = num) (getAutomata ()).trans
 
 (** Initializes some tables according to data from Cil AST. *)
 let setCData () =
@@ -2181,6 +2056,7 @@ let debug_computed_state ?(dkey=dkey) () =
 (* ************************************************************************* *)
 
 let removeUnusedTransitionsAndStates () =
+  let auto = getAutomata () in
   (* Step 1 : computation of reached states and crossed transitions *)
   let treat_one_state state map set =
     Aorai_state.Map.fold
@@ -2192,7 +2068,7 @@ let removeUnusedTransitionsAndStates () =
       (Aorai_state.Set.add state set)
   in
   let reached _ state set = Aorai_state.Map.fold treat_one_state state set in
-  let init = Path_analysis.get_init_states (getAutomata ()) in
+  let init = Path_analysis.get_init_states (getGraph ()) in
   let reached_states = Pre_state.fold reached (Aorai_state.Set.of_list init) in
   let reached_states = Post_state.fold reached reached_states in
   let reached_states = Loop_init_state.fold reached reached_states in
@@ -2221,7 +2097,7 @@ let removeUnusedTransitionsAndStates () =
           (i+1,
            { trans with start = new_start; stop = new_stop; numt = i } :: list)
         with Not_found -> acc)
-      (0,[]) (snd (getAutomata()))
+      (0,[]) auto.trans
   in
   let state_list = List.map new_state state_list in
   Reject_state.may
@@ -2231,7 +2107,7 @@ let removeUnusedTransitionsAndStates () =
         Reject_state.set new_reject
       with Not_found -> Reject_state.clear ());
   (* Step 3 : rewriting stored information *)
-  automata:= (state_list,trans_list);
+  automata := Some { auto with states =state_list; trans = trans_list };
   check_states "reduced automata";
 
   let rewrite_state state =
diff --git a/src/plugins/aorai/data_for_aorai.mli b/src/plugins/aorai/data_for_aorai.mli
index 908c003cf9a1791f3ebf9e0e0ff225a43e83a6db..2d440c0e0e881aaf4346133cb80ed4c0034ad177 100644
--- a/src/plugins/aorai/data_for_aorai.mli
+++ b/src/plugins/aorai/data_for_aorai.mli
@@ -56,7 +56,6 @@ val add_logic : string -> Cil_types.logic_info -> unit
 (** *)
 val get_logic : string -> Cil_types.logic_info
 
-val global_table : varinfo Datatype.String.Map.t ref
 (** *)
 val add_predicate : string -> Cil_types.logic_info -> unit
 
@@ -207,6 +206,9 @@ val new_trans: state -> state -> 'a -> 'a trans
 (** Return the buchi automata as stored after parsing *)
 val getAutomata : unit -> Promelaast.typed_automaton
 
+(** Return only the graph part of the automata *)
+val getGraph : unit -> state list * (typed_condition * action) trans list
+
 (** Type-checks the parsed automaton and stores the result.
     This might introduce new global variables in case of sequences.
 *)
diff --git a/src/plugins/aorai/promelaast.mli b/src/plugins/aorai/promelaast.mli
index 38bc6845c73736023f7ba5f208fc86170d73aa91..3f7ac668c9f4195a43edebe8f82d7b6e89a126c4 100644
--- a/src/plugins/aorai/promelaast.mli
+++ b/src/plugins/aorai/promelaast.mli
@@ -27,9 +27,9 @@
     parser/lexer before its translation into Data_for_aorai module. *)
 
 type expression =
-  | AVar of string (* Metavariable *)
   | PVar of string
   | PPrm of string * string (* f().N *)
+  | PMetavar of string
   | PCst of Logic_ptree.constant
   | PBinop of Logic_ptree.binop * expression * expression
   | PUnop of Logic_ptree.unop * expression
@@ -47,7 +47,7 @@ type condition =
   | PCall of string * string option
       (** Call might be done in a given behavior *)
   | PReturn of string
-  | AfVar of string * expression
+  | PAssign of string * expression
 
 and seq_elt =
     { condition: condition option;
@@ -133,7 +133,11 @@ type 'condition trans =
     }
 
 (** Internal representation of a Buchi automata : a list of states and a list of transitions.*)
-type 'condition automaton = (state list) * ('condition trans list)
+type 'condition automaton = {
+  states: state list;
+  trans: ('condition trans) list;
+  metavariables: Cil_types.varinfo Datatype.String.Map.t;
+}
 
 type parsed_automaton = parsed_condition automaton
 
diff --git a/src/plugins/aorai/promelaoutput.ml b/src/plugins/aorai/promelaoutput.ml
index 4e8bc5969d2095307b01ec11d8db9d1baefa61e2..85afe95f6ed1ec1e5c2a0199398ec14c9d0d5bc3 100644
--- a/src/plugins/aorai/promelaoutput.ml
+++ b/src/plugins/aorai/promelaoutput.ml
@@ -39,6 +39,7 @@ let string_of_unop = function
 let rec print_parsed_expression fmt = function
   | PVar s -> Format.fprintf fmt "%s" s
   | PPrm (f,s) -> Format.fprintf fmt "%s().%s" f s
+  | PMetavar s -> Format.fprintf fmt "$%s" s
   | PCst (IntConstant s) -> Format.fprintf fmt "%s" s
   | PCst (FloatConstant s) -> Format.fprintf fmt "%s" s
   | PCst (StringConstant s) -> Format.fprintf fmt "%S" s
@@ -54,7 +55,6 @@ let rec print_parsed_expression fmt = function
     print_parsed_expression e1 print_parsed_expression e2
   | PField(e,s) -> Format.fprintf fmt "%a.%s" print_parsed_expression e s
   | PArrow(e,s) -> Format.fprintf fmt "%a->%s" print_parsed_expression e s
-  | AVar s -> Format.fprintf fmt "%s" s
 
 let rec print_parsed_condition fmt = function
   | PRel(rel,e1,e2) ->
@@ -73,7 +73,7 @@ let rec print_parsed_condition fmt = function
   | PCall (s,None) -> Format.fprintf fmt "CALL(%s)" s
   | PCall (s, Some b) -> Format.fprintf fmt "CALL(%s::%s)" s b
   | PReturn s -> Format.fprintf fmt "RETURN(%s)" s
-  | AfVar (s, e) -> Format.fprintf fmt " %s := %a " s print_parsed_expression e
+  | PAssign (s, e) -> Format.fprintf fmt " %s := %a " s print_parsed_expression e
 
 let rec print_seq_elt fmt elt =
   Format.fprintf fmt "(%a%a){@[%a,%a@]}"
@@ -187,9 +187,9 @@ let print_statel fmt stl =
   Format.fprintf fmt "@[<2>States:@\n%a@]"
     (Pretty_utils.pp_list ~sep:"@\n" ~suf:"@\n" print_state) stl
 
-let print_raw_automata fmt (stl,trl) =
+let print_raw_automata fmt auto =
   Format.fprintf fmt "@[<2>Automaton:@\n%a%a@]"
-    print_statel stl print_transitionl trl
+    print_statel auto.states print_transitionl auto.trans
 
 let dot_state out st =
   let shape =
@@ -213,7 +213,7 @@ let dot_trans out tr =
     print_state_label tr.stop
     print_label tr
 
-let output_dot_automata (states_l,trans_l) fichier =
+let output_dot_automata {states ; trans} fichier =
   let cout = open_out fichier in
   let fmt = formatter_of_out_channel cout in
   let output_functions = escape_newline fmt in
@@ -236,13 +236,13 @@ let output_dot_automata (states_l,trans_l) fichier =
   one_line_comment "    dot property.dot -Tps > property.ps";
   Format.fprintf fmt "@[<2>@\ndigraph %s {@\n@\n%a@\n%a@\n%t}@\n@]"
     (Filename.chop_extension (Filename.basename fichier))
-    (Pretty_utils.pp_list dot_state) states_l
-    (Pretty_utils.pp_list dot_trans) trans_l
+    (Pretty_utils.pp_list dot_state) states
+    (Pretty_utils.pp_list dot_trans) trans
     (fun fmt ->
       if DotSeparatedLabels.get () then
         (Format.fprintf fmt
            "/* guards of transitions */@\ncomment=\"%a\";@\n"
-           (Pretty_utils.pp_list ~sep:"@\n" print_trans) trans_l));
+           (Pretty_utils.pp_list ~sep:"@\n" print_trans) trans));
   Format.pp_set_formatter_out_functions fmt output_functions;
   close_out cout
 
diff --git a/src/plugins/aorai/promelaparser.mly b/src/plugins/aorai/promelaparser.mly
index bae7efad71dad89aa34e2fa47ef4dea5cbda5de2..2946304bdbeba34476341be5a3471f92db860788 100644
--- a/src/plugins/aorai/promelaparser.mly
+++ b/src/plugins/aorai/promelaparser.mly
@@ -77,7 +77,7 @@ promela
                 st::l
               ) observed_states []
             in
-            (states , $3)
+            { states; trans = $3; metavariables = Datatype.String.Map.empty }
         }
         | PROMELA_NEVER PROMELA_LBRACE states PROMELA_SEMICOLON 
             PROMELA_RBRACE EOF {
@@ -91,7 +91,7 @@ promela
                   st::l
                 ) observed_states []
               in
-              (states , $3) }
+              { states; trans = $3; metavariables = Datatype.String.Map.empty } }
   ;
 
 states   
diff --git a/src/plugins/aorai/promelaparser_withexps.mly b/src/plugins/aorai/promelaparser_withexps.mly
index 36f93360a5037fe1805b122424f6be432fa8c681..1fd125c99c7ae122256cc1f512f116e16dcc159f 100644
--- a/src/plugins/aorai/promelaparser_withexps.mly
+++ b/src/plugins/aorai/promelaparser_withexps.mly
@@ -88,7 +88,7 @@ promela
                 st::l
               ) observed_states []
             in
-            (states , $3)
+            { states; trans = $3; metavariables = Datatype.String.Map.empty }
         }
         | PROMELA_NEVER PROMELA_LBRACE states 
             PROMELA_SEMICOLON PROMELA_RBRACE EOF {
@@ -102,7 +102,7 @@ promela
                 st::l
               ) observed_states []
             in
-            (states , $3) }
+            { states; trans = $3; metavariables = Datatype.String.Map.empty } }
   ;
 
 states   
diff --git a/src/plugins/aorai/yaparser.mly b/src/plugins/aorai/yaparser.mly
index bc494754928b3af104a3d3f2016a20b45923b4cc..732342c02fbcb7ef139f70af0a6b3872f371b838 100644
--- a/src/plugins/aorai/yaparser.mly
+++ b/src/plugins/aorai/yaparser.mly
@@ -46,6 +46,7 @@ let is_no_repet (min,max) =
 
 let observed_states      = Hashtbl.create 1
 let prefetched_states    = Hashtbl.create 1
+let metavariables        = ref Datatype.String.Map.empty
 
 let fetch_and_create_state name =
   Hashtbl.remove prefetched_states name ;
@@ -80,7 +81,7 @@ let add_metavariable name typename =
         typename name
   in
   let vi = Cil.makeGlobalVar (Data_for_aorai.get_fresh ("aorai_" ^ name)) ty in
-  Data_for_aorai.global_table := Datatype.String.Map.add name vi !Data_for_aorai.global_table
+  metavariables := Datatype.String.Map.add name vi !metavariables
 
 
 type pre_cond = Behavior of string | Pre of Promelaast.condition
@@ -156,7 +157,7 @@ main
              end;
            st::l)
         observed_states []
-    in
+    and trans = $2 in
     (try
        Hashtbl.iter
          (fun _ st -> if st.init=True then raise Exit) observed_states;
@@ -172,7 +173,7 @@ main
         in
         Aorai_option.abort "%s" r
       end;
-    (states, $2)
+    { states; trans; metavariables = !metavariables }
   }
   ;
 
@@ -330,16 +331,12 @@ single_cond:
   | RETURN_OF  LPAREN IDENTIFIER RPAREN { PReturn $3 }
   | TRUE { PTrue }
   | FALSE { PFalse }
-  /*TODO*/
-  | NOT single_cond { match $2 with
-    | AfVar(_, _) -> Aorai_option.abort "Not corresponding to program" (*Parsing.symbol_end_pos*)
-    | _ -> PNot $2 }
+  | NOT single_cond { PNot $2 }
   | single_cond AND single_cond { PAnd ($1,$3) }
   | single_cond OR single_cond { POr ($1,$3) }
   | LPAREN single_cond RPAREN { $2 }
   | logic_relation { $1 }
-/*TODO*/
-  | VAR IDENTIFIER AFF arith_relation { AfVar($2, $4) }
+  | VAR IDENTIFIER AFF arith_relation { PAssign ($2, $4) }
 ;
 
 logic_relation
@@ -391,6 +388,5 @@ access_leaf
   | IDENTIFIER LPAREN RPAREN DOT IDENTIFIER { PPrm($1,$5) }
   | IDENTIFIER { PVar $1 }
   | LPAREN access RPAREN { $2 }
-/*TODO*/
-  | VAR IDENTIFIER { AVar($2) }
+  | VAR IDENTIFIER { PMetavar $2 }
   ;