summaryrefslogtreecommitdiff
path: root/src/rewriter.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/rewriter.ml')
-rw-r--r--src/rewriter.ml54
1 files changed, 43 insertions, 11 deletions
diff --git a/src/rewriter.ml b/src/rewriter.ml
index b180b0a1..78b29200 100644
--- a/src/rewriter.ml
+++ b/src/rewriter.ml
@@ -2183,6 +2183,15 @@ let id_is_local_var id env = match Env.lookup_id id env with
| Local _ -> true
| _ -> false
+let rec lexp_is_local (LEXP_aux (lexp, _)) env = match lexp with
+ | LEXP_memory _ -> false
+ | LEXP_id id
+ | LEXP_cast (_, id) -> id_is_local_var id env
+ | LEXP_tup lexps -> List.for_all (fun lexp -> lexp_is_local lexp env) lexps
+ | LEXP_vector (lexp,_)
+ | LEXP_vector_range (lexp,_,_)
+ | LEXP_field (lexp,_) -> lexp_is_local lexp env
+
let id_is_unbound id env = match Env.lookup_id id env with
| Unbound -> true
| _ -> false
@@ -2203,6 +2212,13 @@ let lexp_is_effectful (LEXP_aux (_, (_, annot))) = match annot with
let rec rewrite_local_lexp ((LEXP_aux(lexp,((l,_) as annot))) as le) = match lexp with
| LEXP_id id | LEXP_cast (_, id) ->
(le, E_aux (E_id id, annot), (fun exp -> exp))
+ | LEXP_tup les ->
+ let get_id (LEXP_aux(lexp,((l,_) as annot)) as le) = match lexp with
+ | LEXP_id id | LEXP_cast (_, id) -> E_aux (E_id id, annot)
+ | _ ->
+ raise (Reporting_basic.err_unreachable l
+ ("Unsupported sub-lexp " ^ string_of_lexp le ^ " in tuple")) in
+ (le, E_aux (E_tuple (List.map get_id les), annot), (fun exp -> exp))
| LEXP_vector (lexp, e) ->
let (lexp, access, rexp) = rewrite_local_lexp lexp in
(lexp, E_aux (E_vector_access (access, e), annot),
@@ -2233,7 +2249,7 @@ let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as f
let rec walker exps = match exps with
| [] -> []
| (E_aux(E_assign(le,e), ((l, Some (env,typ,eff)) as annot)) as exp)::exps
- when lexp_is_local_intro le env && not (lexp_is_effectful le)->
+ when lexp_is_local_intro le env && not (lexp_is_effectful le) ->
let (le', _, re') = rewrite_local_lexp le in
let e' = re' (rewrite_base e) in
let exps' = walker exps in
@@ -2371,12 +2387,11 @@ let rewrite_defs_early_return =
| _ -> exp in
let e_block es =
- (* let rec walker = function
- | e :: es -> if is_return e then [e] else e :: walker es
- | [] -> [] in
- let es = walker es in *)
match es with
| [E_aux (e, _)] -> e
+ | _ :: _ when is_return (Util.last es) ->
+ let (E_aux (_, annot) as e) = Util.last es in
+ E_return (E_aux (E_block (Util.butlast es @ [get_return e]), annot))
| _ -> E_block es in
let e_if (e1, e2, e3) =
@@ -2404,14 +2419,19 @@ let rewrite_defs_early_return =
| _ -> full_exp in
let rewrite_funcl_early_return _ (FCL_aux (FCL_Funcl (id, pat, exp), a)) =
- let exp = fold_exp
- { id_exp_alg with e_block = e_block; e_if = e_if; e_case = e_case;
- e_aux = e_aux } exp in
+ let exp =
+ exp
+ (* Pull early returns out as far as possible *)
+ |> fold_exp { id_exp_alg with e_block = e_block; e_if = e_if; e_case = e_case }
+ (* Remove singleton E_return *)
+ |> get_return
+ (* Fix effect annotations *)
+ |> fold_exp { id_exp_alg with e_aux = e_aux } in
let a = match a with
| (l, Some (env, typ, eff)) ->
(l, Some (env, typ, union_effects eff (effect_of exp)))
| _ -> a in
- FCL_aux (FCL_Funcl (id, pat, get_return exp), a) in
+ FCL_aux (FCL_Funcl (id, pat, exp), a) in
let rewrite_fun_early_return rewriters
(FD_aux (FD_function (rec_opt, tannot_opt, effect_opt, funcls), a)) =
@@ -2948,8 +2968,19 @@ let rewrite_defs_letbind_effects =
let rewrite_defs_effectful_let_expressions =
+ let rec pat_of_local_lexp (LEXP_aux (lexp, ((l, _) as annot))) = match lexp with
+ | LEXP_id id -> P_aux (P_id id, annot)
+ | LEXP_cast (typ, id) -> P_aux (P_typ (typ, P_aux (P_id id, annot)), annot)
+ | LEXP_tup lexps -> P_aux (P_tup (List.map pat_of_local_lexp lexps), annot)
+ | _ -> raise (Reporting_basic.err_unreachable l "unexpected local lexp") in
+
let e_let (lb,body) =
match lb with
+ | LB_aux (LB_val_implicit (P_aux (P_wild, _), E_aux (E_assign ((LEXP_aux (_, annot) as le), exp), _)), _)
+ when lexp_is_local le (env_of_annot annot) ->
+ (* Rewrite assignments to local variables into let bindings *)
+ let (lhs, _, rhs) = rewrite_local_lexp le in
+ E_let (LB_aux (LB_val_implicit (pat_of_local_lexp lhs, rhs exp), annot), body)
| LB_aux (LB_val_explicit (_,pat,exp'),annot')
| LB_aux (LB_val_implicit (pat,exp'),annot') ->
if effectful exp'
@@ -3261,7 +3292,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
"tail-position": check the definition nexp_term and where it is used. *)
| _ -> exp
-let replace_memwrite_e_assign exp =
+let replace_memwrite_e_assign exp =
let e_aux = fun (expaux,annot) ->
match expaux with
| E_assign (LEXP_aux (LEXP_memory (id,args),_),v) -> E_aux (E_app (id,args @ [v]),annot)
@@ -3395,7 +3426,8 @@ let rewrite_defs_remove_e_assign =
let recheck_defs defs = fst (check initial_env defs)
let rewrite_defs_lem =[
- top_sort_defs;
+ (* top_sort_defs; *)
+ rewrite_trivial_sizeof;
rewrite_sizeof;
rewrite_defs_remove_vector_concat;
rewrite_defs_remove_bitvector_pats;