Ported transformations

A BIG Refactoring is needed
This commit is contained in:
Cédric Pasteur 2010-06-17 14:38:28 +02:00 committed by Léonard Gérard
parent ca38c3ba44
commit a0cc9917ac
6 changed files with 176 additions and 189 deletions

View file

@ -150,19 +150,38 @@ type interface =
and interface_desc =
| Iopen of name | Itypedef of type_dec | Isignature of signature
(* Helper functions to create AST. *) (*TODO refactor en mk_*)
(* Helper functions to create AST. *)
let mk_exp desc ty =
{ e_desc = desc; e_ty = ty; e_loc = no_location; }
let mk_op op = { a_op = op; }
let mk_op_desc ln params kind =
{ op_name = ln; op_params = params; op_kind = kind }
let mk_type_dec name desc =
{ t_name = name; t_desc = desc; t_loc = no_location; }
let mk_equation desc =
{ eq_desc = desc; eq_statefull = true; eq_loc = no_location; }
let mk_equation ?(statefull = true) desc =
{ eq_desc = desc; eq_statefull = statefull; eq_loc = no_location; }
let mk_var_dec ?(last = Var) name ty =
{ v_name = name; v_type = ty;
v_last = last; v_loc = Location.get_current_location () }
let mk_block defnames eqs =
{ b_local = []; b_equs = eqs; b_defnames = defnames;
b_statefull = true; b_loc = no_location }
let dfalse = mk_exp (Econst (Cconstr Initial.pfalse)) (Tid Initial.pbool)
let dtrue = mk_exp (Econst (Cconstr Initial.ptrue)) (Tid Initial.pbool)
let mk_ifthenelse e1 e2 e3 =
{ e3 with e_desc = Eapp(mk_op Eifthenelse, [e1; e2; e3]) }
let mk_simple_equation pat e =
mk_equation ~statefull:false (Eeq(pat, e))
(*
let cfalse = Cconstr Initial.pfalse

View file

@ -10,26 +10,30 @@
(* $Id$ *)
open Location
open Misc
open Names
open Ident
open Heptagon
open Global
open Initial
open Interference_graph
open Types
let rename_states env g =
let rename_one n =
try
let olds = List.hd n.g_content in
let s = NamesEnv.find olds env in
Hashtbl.remove g.g_hash olds;
Hashtbl.add g.g_hash s n;
n.g_content <- [s]
with Not_found -> ()
in
List.iter rename_one g.g_nodes
let mk_var_exp n ty =
mk_exp (Evar n) ty
let mk_pair e1 e2 =
mk_exp (Etuple [e1;e2]) (Tprod [e1.e_ty; e2.e_ty])
let mk_reset_equation eq_list e =
mk_equation (Ereset (eq_list, e))
let mk_switch_equation e l =
mk_equation (Eswitch (e, l))
let mk_exp_fby_false e =
mk_exp (Eapp(mk_op (Epre (Some (Cconstr Initial.pfalse))), [e]))
(Tid Initial.pbool)
let mk_exp_fby_state initial e =
{ e with e_desc = Eapp(mk_op (Epre (Some (Cconstr initial))), [e]) }
(* the list of enumerated types introduced to represent states *)
let state_type_dec_list = ref []
@ -39,8 +43,8 @@ let intro_type states =
let n = gen_symbol () in
let state_type = "st" ^ n in
state_type_dec_list :=
(tmake state_type (Type_enum(list states))) :: !state_type_dec_list;
Name(state_type)
(mk_type_dec state_type (Type_enum (list states))) :: !state_type_dec_list;
Name(state_type)
(* an automaton may be a Moore automaton, i.e., with only weak transitions; *)
(* a Mealy one, i.e., with only strong transition or mixed *)
@ -49,41 +53,41 @@ let moore_mealy state_handlers =
(moore or (l1 <> []), mealy or (l2 <> [])) in
List.fold_left handler (false, false) state_handlers
let rec translate_eq g (v, eq_list) eq =
let rec translate_eq (v, eq_list) eq =
match eq.eq_desc with
Eautomaton(state_handlers) ->
translate_automaton g v eq_list state_handlers
translate_automaton v eq_list state_handlers
| Eswitch(e, switch_handlers) ->
v,
{ eq with eq_desc =
Eswitch(e, translate_switch_handlers g switch_handlers) }
Eswitch(e, translate_switch_handlers switch_handlers) }
:: eq_list
| Epresent(present_handlers, block) ->
v, { eq with eq_desc =
Epresent(translate_present_handlers g present_handlers,
translate_block g block) } :: eq_list
Epresent(translate_present_handlers present_handlers,
translate_block block) } :: eq_list
| Ereset(r_eq_list, e) ->
let v, r_eq_list = translate_eqs g v r_eq_list in
let v, r_eq_list = translate_eqs v r_eq_list in
v, { eq with eq_desc = Ereset(r_eq_list, e) } :: eq_list
| Eeq _ -> v, eq :: eq_list
and translate_eqs g v eq_list = List.fold_left (translate_eq g) (v, []) eq_list
and translate_eqs v eq_list = List.fold_left translate_eq (v, []) eq_list
and translate_block g ({ b_local = v; b_equs = eq_list } as b) =
let v, eq_list = translate_eqs g v eq_list in
and translate_block ({ b_local = v; b_equs = eq_list } as b) =
let v, eq_list = translate_eqs v eq_list in
{ b with b_local = v; b_equs = eq_list }
and translate_switch_handlers g handlers =
and translate_switch_handlers handlers =
let translate_switch_handler { w_name = n; w_block = b } =
{ w_name = n; w_block = translate_block g b } in
{ w_name = n; w_block = translate_block b } in
List.map translate_switch_handler handlers
and translate_present_handlers g handlers =
and translate_present_handlers handlers =
let translate_present_handler { p_cond = e; p_block = b } =
{ p_cond = e; p_block = translate_block g b } in
{ p_cond = e; p_block = translate_block b } in
List.map translate_present_handler handlers
and translate_automaton g v eq_list handlers =
and translate_automaton v eq_list handlers =
let has_until, has_unless = moore_mealy handlers in
let states =
let suffix = gen_symbol () in
@ -92,7 +96,7 @@ and translate_automaton g v eq_list handlers =
NamesEnv.empty handlers in
let statetype = intro_type states in
let tstatetype = Tbase(Tid(statetype)) in
let tstatetype = Tid statetype in
let initial = Name(NamesEnv.find (List.hd handlers).s_state states) in
let statename = Ident.fresh "s" in
@ -101,84 +105,80 @@ and translate_automaton g v eq_list handlers =
let next_resetname = Ident.fresh "nr" in
let pre_next_resetname = Ident.fresh "pnr" in
(* update the states graph with the suffixed names *)
rename_states states g;
let name n = Name(NamesEnv.find n states) in
let state n =
emake (Econst(Cconstr(name n))) tstatetype in
let statevar n = var n tstatetype in
let boolvar n = var n tybool in
let state n = mk_exp (Econst (Cconstr (name n))) tstatetype in
let statevar n = mk_var_exp n tstatetype in
let boolvar n = mk_var_exp n (Tid Initial.pbool) in
let escapes n s rcont =
let escape { e_cond = e; e_reset = r; e_next_state = n } cont =
ifthenelse e (pair (state n) (if r then dtrue else dfalse)) cont in
List.fold_right escape s (pair (state n) rcont) in
mk_ifthenelse e (mk_pair (state n) (if r then dtrue else dfalse)) cont in
List.fold_right escape s (mk_pair (state n) rcont) in
let strong { s_state = n; s_unless = su } =
block
mk_block
(Env.add statename tstatetype
(Env.add resetname tybool Env.empty))
([reset(
[eq (Etuplepat[Evarpat(statename);Evarpat(resetname)])
(Env.add resetname (Tid Initial.pbool) Env.empty))
([mk_reset_equation (
[mk_simple_equation (Etuplepat[Evarpat(statename);Evarpat(resetname)])
(escapes n su (boolvar pre_next_resetname))])
(boolvar pre_next_resetname)]) in
let weak { s_state = n; s_block = b; s_until = su } =
let b = translate_block g b in
let b = translate_block b in
{ b with b_equs =
[reset ((eq (Etuplepat[Evarpat(next_statename);
[mk_reset_equation ((mk_simple_equation (Etuplepat[Evarpat(next_statename);
Evarpat(next_resetname)])
(escapes n su dfalse)) :: b.b_equs)
(boolvar resetname)];
(* (or_op (boolvar pre_next_resetname) (boolvar resetname))]; *)
b_defnames =
Env.add next_statename tstatetype
(Env.add next_resetname tybool
(Env.add next_resetname (Tid Initial.pbool)
b.b_defnames)
} in
let v =
(param next_statename (Tid(statetype))) ::
(param resetname tbool) ::
(param next_resetname tbool) ::
(param pre_next_resetname tbool) :: v in
(mk_var_dec next_statename (Tid(statetype))) ::
(mk_var_dec resetname (Tid Initial.pbool)) ::
(mk_var_dec next_resetname (Tid Initial.pbool)) ::
(mk_var_dec pre_next_resetname (Tid Initial.pbool)) :: v in
(* we optimise the case of an only strong automaton *)
(* or only weak automaton *)
match has_until, has_unless with
| true, false ->
(* a Moore automaton with only weak transitions *)
v, (switch (fby_state initial (statevar next_statename))
v, (mk_switch_equation (mk_exp_fby_state initial (statevar next_statename))
(List.map
(fun ({ s_state = n } as case) ->
{ w_name = name n; w_block = weak case })
handlers)) ::
(eq (Evarpat pre_next_resetname)
(fby_false (boolvar (next_resetname)))) ::
(eq (Evarpat resetname) (boolvar pre_next_resetname)) :: eq_list
(mk_simple_equation (Evarpat pre_next_resetname)
(mk_exp_fby_false (boolvar (next_resetname)))) ::
(mk_simple_equation (Evarpat resetname) (boolvar pre_next_resetname)) :: eq_list
| _ ->
(* the general case; two switch to generate,
statename variable used and defined *)
(param statename (Tid(statetype))) :: v,
(switch (fby_state initial (statevar next_statename))
(mk_var_dec statename (Tid statetype)) :: v,
(mk_switch_equation (mk_exp_fby_state initial (statevar next_statename))
(List.map
(fun ({ s_state = n } as case) ->
{ w_name = name n; w_block = strong case })
handlers)) ::
(switch (statevar statename)
(mk_switch_equation (statevar statename)
(List.map
(fun ({ s_state = n } as case) ->
{ w_name = name n; w_block = weak case })
handlers)) ::
(eq (Evarpat pre_next_resetname)
(fby_false (boolvar (next_resetname)))) ::
(mk_simple_equation (Evarpat pre_next_resetname)
(mk_exp_fby_false (boolvar (next_resetname)))) ::
eq_list
let translate_contract g ({ c_local = v; c_eq = eq_list} as c) =
let v, eq_list = translate_eqs g v eq_list in
let translate_contract ({ c_local = v; c_eq = eq_list} as c) =
let v, eq_list = translate_eqs v eq_list in
{ c with c_local = v; c_eq = eq_list }
let node ({ n_local = v; n_equs = eq_list; n_contract = contract; n_states_graph = g } as n) =
let v, eq_list = translate_eqs g v eq_list in
let contract = optional (translate_contract g) contract in
let node ({ n_local = v; n_equs = eq_list; n_contract = contract } as n) =
let v, eq_list = translate_eqs v eq_list in
let contract = optional translate_contract contract in
{ n with n_local = v; n_equs = eq_list; n_contract = contract }
let program ({ p_types = pt_list; p_nodes = n_list } as p) =

View file

@ -8,25 +8,19 @@
(**************************************************************************)
(* complete partial definitions with [x = last(x)] *)
(* $Id$ *)
open Location
open Ident
open Misc
open Heptagon
open Global
open Ident
(* adds an equation [x = last(x)] for every partially defined variable *)
(* in a control structure *)
let complete_with_last defined_names local_defined_names eq_list =
let last n ty =
{ e_desc = Elast(n); e_ty = ty; e_linearity = Linearity.NotLinear;
e_loc = no_location } in
let last n ty = mk_exp (Elast n) ty in
let equation n ty eq_list =
{ eq_desc = Eeq(Evarpat(n), last n ty); eq_statefull = false;
eq_loc = no_location } :: eq_list in
(mk_equation (Eeq(Evarpat n, last n ty)))::eq_list
in
let d = Env.diff defined_names local_defined_names in
Env.fold equation d eq_list
Env.fold equation d eq_list
let rec translate_eq eq =
match eq.eq_desc with

View file

@ -15,42 +15,11 @@
x = (f every r) e'
*)
(* $Id$ *)
open Location
open Misc
open Ident
open Heptagon
open Global
open Initial
open Reset
let eq pat e =
{ eq_desc = Eeq(pat, e); eq_statefull = false; eq_loc = no_location }
let statefulleq = Heptagon.eq
(* add an equation *)
let equation v acc_eq_list e =
let n = Ident.fresh "r" in
n,
(bool_param n) :: v,
{ eq_desc = Eeq(Evarpat(n), e); eq_statefull = true; eq_loc = e.e_loc } ::
acc_eq_list
let orthen v acc_eq_list res e =
match e.e_desc with
Evar(n) -> v, acc_eq_list, Rorthen(res, n)
| _ ->
let n, v, acc_eq_list = equation v acc_eq_list e in
v, acc_eq_list, Rorthen(res, n)
let add_locals m n locals =
let rec loop locals i n =
if i < n then
loop ((bool_param m.(i)) :: locals) (i+1) n
else locals in
loop locals 0 n
(*
let defnames m n d =
let rec loop acc k = if k < n then loop (S.add m.(k) acc) (k+1) else acc in
@ -60,7 +29,7 @@ let defnames m n d =
let statefull eq_list = List.exists (fun eq -> eq.eq_statefull) eq_list
let is_var = function
| { e_desc = Evar(_) } -> true
| { e_desc = Evar _ } -> true
| _ -> false
let rec translate_eq v acc_eq_list eq =
@ -102,25 +71,27 @@ and translate v acc_eq_list e =
| Etuple(e_list) ->
let v, acc_eq_list,e_list = translate_list v acc_eq_list e_list in
v,acc_eq_list,
{ e with e_desc = Etuple(e_list) }
| Eapp({ a_op = Eevery(f,params) } as op, re :: e_list)
{ e with e_desc = Etuple e_list }
| Eapp ({ a_op = Ecall(op_desc, Some re) } as op, e_list)
when not (is_var re) ->
let v, acc_eq_list,re = translate v acc_eq_list re in
let n, v, acc_eq_list = equation v acc_eq_list re in
let v, acc_eq_list, e_list = translate_list v acc_eq_list e_list in
v,acc_eq_list,
v,acc_eq_list,
{ e with e_desc =
Eapp({ op with a_op = Eevery(f,params) },
{ re with e_desc = Evar(n) } :: e_list) }
| Eapp({ a_op = Eiterator(it, f, params, Some re) } as op, e_list)
when not (is_var re) ->
Eapp({ op with a_op = Ecall(op_desc,
Some { re with e_desc = Evar(n) }) },
e_list) }
| Eapp ({ a_op = Earray_op(Eiterator(it, op_desc, Some re)) } as op, e_list)
when not (is_var re) ->
let v, acc_eq_list,re = translate v acc_eq_list re in
let n, v, acc_eq_list = equation v acc_eq_list re in
let v, acc_eq_list, e_list = translate_list v acc_eq_list e_list in
let re = { re with e_desc = Evar n } in
v,acc_eq_list,
let re = { re with e_desc = Evar n } in
v,acc_eq_list,
{ e with e_desc =
Eapp({ op with a_op = Eiterator(it, f, params, Some re) },e_list) }
Eapp({ op with a_op = Earray_op(Eiterator(it, op_desc, Some re)) },
e_list) }
| Eapp(f, e_list) ->
let v, acc_eq_list, e_list = translate_list v acc_eq_list e_list in
v, acc_eq_list,
@ -142,7 +113,6 @@ and translate v acc_eq_list e =
let v, acc_eq_list,e_list = translate_list v acc_eq_list e_list in
v,acc_eq_list,
{ e with e_desc = Earray(e_list) }
| Ereset_mem _ -> v,acc_eq_list,e
and translate_list v acc_eq_list e_list =
let v,acc_eq_list,acc_e =

View file

@ -8,13 +8,9 @@
(**************************************************************************)
(* removing accessed to shared variables (last x) *)
(* $Id$ *)
open Location
open Misc
open Ident
open Heptagon
open Global
open Ident
(* introduce a fresh equation [last_x = pre(x)] for every *)
(* variable declared with a last *)
@ -23,15 +19,13 @@ let last (eq_list, env, v) { v_name = n; v_type = t; v_last = last } =
| Var -> (eq_list, env, v)
| Last(default) ->
let lastn = Ident.fresh ("last" ^ (sourcename n)) in
(eqmake (Eeq(Evarpat(lastn),
emake
(Eapp (eop (Epre(default)),
[emake (Evar(n)) (Tbase(t))]))
(Tbase(t)))))
:: eq_list,
let eq = mk_equation (Eeq (Evarpat lastn,
mk_exp (Eapp (mk_op (Epre default),
[mk_exp (Evar n) t])) t)) in
eq:: eq_list,
Env.add n lastn env,
(param lastn t) :: v
(mk_var_dec lastn t) :: v
let extend_env env v = List.fold_left last ([], env, []) v
let rec translate_eq env eq =
@ -71,7 +65,6 @@ and translate env e =
Estruct(List.map (fun (f, e) -> (f, translate env e)) e_f_list) }
| Earray(e_list) ->
{ e with e_desc = Earray(List.map (translate env) e_list) }
| Ereset_mem _ -> assert false
let translate_contract env contract =
match contract with

View file

@ -10,12 +10,10 @@
(* $Id$ *)
open Location
open Misc
open Ident
open Heptagon
open Global
open Initial
open Types
(* We introduce an initialization variable for each block *)
(* Using an asynchronous reset would allow to produce *)
@ -43,14 +41,16 @@ open Initial
e1 -> e2 is translated into if (true fby false) then e1 else e2
*)
let mk_bool_var n =
mk_exp (Evar n) (Tid Initial.pbool)
let mk_bool_param n =
mk_var_dec n (Tid Initial.pbool)
let or_op_call = mk_op ( Ecall(mk_op_desc Initial.por [] Eop, None) )
let pre_true e =
{ e with e_desc = Eapp(eop (Epre(Some(Cconstr(ptrue)))), [e]) }
{ e with e_desc = Eapp(mk_op (Epre (Some (Cconstr Initial.ptrue))), [e]) }
let init e = pre_true { dfalse with e_loc = e.e_loc }
let ifthenelse e1 e2 e3 =
{ e3 with e_desc = Eapp(eop Eifthenelse, [e1; e2; e3]) }
let eq pat e =
{ eq_desc = Eeq(pat, e); eq_statefull = false; eq_loc = no_location }
let statefulleq = Heptagon.eq
(* the boolean condition for a structural reset *)
type reset =
@ -68,31 +68,30 @@ let rec or_op res e =
match res with
| Rfalse -> e
| Rorthen(res, n) ->
or_op res { e with e_desc = Eapp(eop (Eop(por,[])), [bool_var n; e]) }
or_op res { e with e_desc = Eapp(or_op_call, [mk_bool_var n; e]) }
let default e =
match e.e_desc with
| Econst c -> Some(c)
| Econst c -> Some c
| _ -> None
let exp_of_res res =
match res with
| Rfalse -> dfalse
| Rorthen(res, n) -> or_op res (bool_var n)
| Rorthen(res, n) -> or_op res (mk_bool_var n)
let ifres res e2 e3 =
match res with
| Rfalse -> ifthenelse (init e3) e2 e3
| Rfalse -> mk_ifthenelse (init e3) e2 e3
| _ -> (* a reset occurs *)
ifthenelse (exp_of_res res) e2 e3
mk_ifthenelse (exp_of_res res) e2 e3
(* add an equation *)
let equation v acc_eq_list e =
let n = Ident.fresh "r" in
n,
(bool_param n) :: v,
{ eq_desc = Eeq(Evarpat(n), e); eq_statefull = true; eq_loc = e.e_loc } ::
acc_eq_list
(mk_bool_param n) :: v,
(mk_equation (Eeq(Evarpat n, e))) ::acc_eq_list
let orthen v acc_eq_list res e =
match e.e_desc with
@ -104,7 +103,7 @@ let orthen v acc_eq_list res e =
let add_locals m n locals =
let rec loop locals i n =
if i < n then
loop ((bool_param m.(i)) :: locals) (i+1) n
loop ((mk_bool_param m.(i)) :: locals) (i+1) n
else locals in
loop locals 0 n
@ -112,10 +111,10 @@ let add_local_equations i n m lm acc =
(* [mi = false;...; m1 = l_m1;...; mn = l_mn] *)
let rec loop acc k =
if k < n then
if k = i then loop ((eq (varpat(m.(k))) dfalse) :: acc) (k+1)
if k = i then loop ((mk_simple_equation (Evarpat (m.(k))) dfalse) :: acc) (k+1)
else
loop
((eq (varpat(m.(k))) (bool_var lm.(k))) :: acc) (k+1)
((mk_simple_equation (Evarpat (m.(k))) (mk_bool_var lm.(k))) :: acc) (k+1)
else acc
in loop acc 0
@ -124,20 +123,20 @@ let add_global_equations n m lm res acc =
l_mn = if res then true else true fby mn ] *)
let rec loop acc k =
if k < n then
loop
((statefulleq (varpat(lm.(k)))
(match res with
| Rfalse -> pre_true (bool_var m.(k))
| _ -> ifres res dtrue (pre_true (bool_var m.(k)))
)
) :: acc) (k+1)
let exp =
(match res with
| Rfalse -> pre_true (mk_bool_var m.(k))
| _ -> ifres res dtrue (pre_true (mk_bool_var m.(k)))
) in
loop
((mk_equation (Eeq (Evarpat (lm.(k)), exp))) :: acc) (k+1)
else acc in
loop acc 0
let defnames m n d =
let rec loop acc k =
if k < n
then loop (Env.add m.(k) tybool acc) (k+1)
then loop (Env.add m.(k) (Tid Initial.pbool) acc) (k+1)
else acc in
loop d 0
@ -207,37 +206,49 @@ and translate res e =
match res, e1 with
| Rfalse, { e_desc = Econst(c) } ->
(* no reset *)
{ e with e_desc =
Eapp({ op with a_op = Epre(Some(c)) }, [e2]) }
{ e with e_desc =
Eapp({ op with a_op = Epre(Some c) }, [e2]) }
| _ ->
ifres res e1
{ e with e_desc =
Eapp({ op with a_op = Epre(default e1) }, [e2]) }
Eapp({ op with a_op = Epre(default e1) }, [e2]) }
end
| Eapp({ a_op = Earrow }, [e1;e2]) ->
let e1 = translate res e1 in
let e2 = translate res e2 in
ifres res e1 e2
| Eapp({ a_op = Enode(f,params) } as op, e_list) ->
let e_list = List.map (translate res) e_list in
if true_reset res then
{ e with e_desc = Eapp({ op with a_op = Eevery(f, params) },
(exp_of_res res) :: e_list) }
else
{ e with e_desc = Eapp({ op with a_op = Enode(f,params) }, e_list ) }
| Eapp( { a_op = Eiterator(it,f, params, _) } as op, e_list) ->
let e_list = List.map (translate res) e_list in
if true_reset res then
let r = Some (exp_of_res res) in
{ e with e_desc = Eapp({ op with a_op = Eiterator(it,f,params,r) },
e_list) }
else
{ e with e_desc = Eapp(op, e_list) }
| Eapp({ a_op = Eevery(f, params) } as op, re :: e_list) ->
(* add reset to the current reset exp. *)
| Eapp({ a_op = Ecall(op_desc, Some re) } as op, e_list) ->
let re = translate res re in
let e_list = List.map (translate res) e_list in
{ e with e_desc = Eapp({ op with a_op = Eevery(f, params)},
(or_op res re) :: e_list) }
let op = { op with a_op = Ecall(op_desc, Some (or_op res re))} in
{ e with e_desc = Eapp(op, e_list) }
(* create a new reset exp if necessary *)
| Eapp({ a_op = Ecall(op_desc, None) } as op, e_list) ->
let e_list = List.map (translate res) e_list in
if true_reset res then
let op = { op with a_op = Ecall(op_desc, Some (exp_of_res res)) } in
{ e with e_desc = Eapp(op, e_list) }
else
{ e with e_desc = Eapp(op, e_list ) }
(* add reset to the current reset exp. *)
| Eapp( { a_op = Earray_op (Eiterator(it, op_desc, Some re)) } as op, e_list) ->
let re = translate res re in
let e_list = List.map (translate res) e_list in
let r = Some (or_op res re) in
let op = { op with a_op = Earray_op (Eiterator(it, op_desc, r)) } in
{ e with e_desc = Eapp(op, e_list) }
(* create a new reset exp if necessary *)
| Eapp( { a_op = Earray_op (Eiterator(it, op_desc, None)) } as op, e_list) ->
let e_list = List.map (translate res) e_list in
if true_reset res then
let r = Some (exp_of_res res) in
let op = { op with a_op = Earray_op (Eiterator(it, op_desc, r)) } in
{ e with e_desc = Eapp(op, e_list) }
else
{ e with e_desc = Eapp(op, e_list) }
| Eapp(op, e_list) ->
{ e with e_desc = Eapp(op, List.map (translate res) e_list) }
| Efield(e', field) ->