summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rewriter.ml235
1 files changed, 93 insertions, 142 deletions
diff --git a/src/rewriter.ml b/src/rewriter.ml
index 9dbf259a..5f1f16fe 100644
--- a/src/rewriter.ml
+++ b/src/rewriter.ml
@@ -802,229 +802,180 @@ let rewrite_defs_ocaml defs =
let sequentialise_effects_counter = ref 0
let sequentialise_effects exp =
+ let effs (E_aux (_,(l,a))) =
+ match a with
+ | Base((_,t),_,_,_,{effect = Eset effs},_) -> effs
+ | NoTyp -> []
+ | _ -> failwith "sequentialise_effects doesn't support Overload" in
+
+ let effectful eaux =
+ List.exists
+ (fun (BE_aux (be,_)) -> match be with BE_nondet | BE_unspec | BE_undef -> false | _ -> true)
+ (effs eaux) in
+
let compose f g x = f (g x) in
+ let composeL fs = List.fold_left compose (fun x -> x) fs in
let fresh_name () =
let current = !sequentialise_effects_counter in
let () = sequentialise_effects_counter := (current + 1) in
Id_aux (Id ("__w" ^ string_of_int current), Parse_ast.Unknown) in
- let aux (((E_aux (_,annot)) as e,b) : ('a exp * bool)) : (('a exp -> 'a exp) * 'a exp * bool) =
- (* for a tuple (e, b = is e effectful) return
+ let aux (E_aux (_,annot) as e) =
+ (* for a tuple e return
1. a function that let-binds e to the argument (body)
- 2. something to access e's value, which is either e itself if b = false or an id to access the
- value bound to id in the let-expression
- 3. b *)
+ 2. something to access e's value, which is either e itself if e is pure or an id to access the
+ value bound to id in the let-expression if e is effectful *)
- let letbind id body =
- let typ = (Parse_ast.Unknown,simple_annot {t = Tid "unit"}) in
+ let letbind id effs body =
+ let typ = (Parse_ast.Unknown,simple_annot_efr {t = Tid "unit"} effs) in
E_aux (E_let (LB_aux (LB_val_implicit (P_aux (P_id id,annot),e),annot),body),typ) in
- if b then
+ if (effectful e) then
let freshid = fresh_name () in
- let decl = letbind freshid in
- (decl,E_aux (E_id freshid,annot),b)
+ let decl = letbind freshid {effect = Eset (effs e)} in
+ (decl,E_aux (E_id freshid,annot))
else
- ((fun x -> x),e,b) in
+ ((fun x -> x),e) in
let list_aux es =
List.fold_left
- (fun (acc_decl, acc_es, acc_b) e ->
- let (decl,e,b) = aux e in
- (compose acc_decl decl, acc_es @ [e], acc_b || b))
- ((fun x -> x), [], false) es in
+ (fun (acc_decl, acc_es) e ->
+ let (decl,e) = aux e in
+ (compose acc_decl decl, acc_es @ [e]))
+ ((fun x -> x), []) es in
(* for each expression e: return a tuple (e',b) where e' is e rewritten,
b indicates whether e contains effectful terms) *)
fold_exp
- { e_block =
- (fun es ->
- let (decls,es) = List.split es in
- (decls, E_block es)
- )
- ; e_nondet =
- (fun es ->
- let (decls,es) = List.split es in
- (decls, E_block es))
+ { e_block = (fun es -> ((fun x -> x), E_block es))
+ ; e_nondet = (fun es -> ((fun x -> x), E_block es))
; e_id = (fun id -> ((fun x -> x), E_id id))
; e_lit = (fun lit -> ((fun x -> x), E_lit lit))
; e_cast = (fun (typ,e) -> let (decl,e) = aux e in (decl, E_cast (typ,e)))
; e_app = (fun (id,es) -> let (decl,es) = list_aux es in (decl,E_app (id,es)))
; e_app_infix =
(fun (e1,id,e2) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- (compose decl1 decl2, E_app_infix (e1,id,e2), b1 || b2)
- )
- ; e_tuple =
- (fun es ->
- let (decl,es,b) = list_aux es in
- (decl, E_tuple es,b)
- )
- ; e_if =
- (fun (e1,(e2,b2),(e3,b3)) ->
- let (decl,e1,b1) = aux e1 in
- (decl, E_if (e1,e2,e3), b1 || b2 || b3)
+ let ((decl1,e1),(decl2,e2)) = (aux e1,aux e2) in
+ (compose decl1 decl2, E_app_infix (e1,id,e2))
)
+ ; e_tuple = (fun es -> let (decl,es) = list_aux es in (decl, E_tuple es))
+ ; e_if = (fun (e1,e2,e3) -> let (decl,e1) = aux e1 in (decl, E_if (e1,e2,e3)))
; e_for =
- (fun (id,e1,e2,e3,order,(e4,b4)) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- (compose decl1 (compose decl2 decl3), E_for (id,e1,e2,e3,order,e4), b1 || b2 || b3 || b4)
- )
- ; e_vector =
- (fun es ->
- let (decl,es,b) = list_aux es in
- (decl, E_vector es, b)
+ (fun (id,e1,e2,e3,order,e4) ->
+ let ((decl1,e1),(decl2,e2),(decl3,e3)) = (aux e1,aux e2,aux e3) in
+ (composeL [decl1;decl2;decl3], E_for (id,e1,e2,e3,order,e4))
)
+ ; e_vector = (fun es -> let (decl,es) = list_aux es in (decl, E_vector es))
; e_vector_indexed =
- (fun (es,(decl2,opt2,b2)) ->
+ (fun (es,(decl2,opt2)) ->
let (is,es) = List.split es in
- let (decl1,es,b1) = list_aux es in
- (compose decl1 decl2, E_vector_indexed (List.combine is es,opt2), b1 || b2)
+ let (decl1,es) = list_aux es in
+ (compose decl1 decl2, E_vector_indexed (List.combine is es,opt2))
)
; e_vector_access =
(function
- | ((E_aux (E_id _,_) as e1,b1),e2) ->
+ | ((E_aux (E_id _,_) as e1),e2) ->
(* then e1 is OK: the whole e_vector_access has to be
translated to a monadic expression *)
- let (decl2,e2,b2) = aux e2 in
- (decl2, E_vector_access (e1,e2), b1 || b2)
+ let (decl2,e2) = aux e2 in
+ (decl2, E_vector_access (e1,e2))
| (e1,e2) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- (compose decl1 decl2, E_vector_access (e1,e2), b1 || b2)
+ let ((decl1,e1),(decl2,e2)) = (aux e1,aux e2) in
+ (compose decl1 decl2, E_vector_access (e1,e2))
)
; e_vector_subrange =
(function
- | ((E_aux (E_id _,_) as e1,b1),e2,e3) ->
+ | ((E_aux (E_id _,_) as e1),e2,e3) ->
(* then e1 is OK: the whole e_vector_access has to be
translated to a monadic expression *)
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- (compose decl2 decl3, E_vector_subrange (e1,e2,e3), b1 || b2 || b3)
+ let ((decl2,e2),(decl3,e3)) = (aux e2,aux e3) in
+ (compose decl2 decl3, E_vector_subrange (e1,e2,e3))
| (e1,e2,e3) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- (compose decl1 (compose decl2 decl3), E_vector_subrange (e1,e2,e3), b1 || b2)
+ let ((decl1,e1),(decl2,e2),(decl3,e3)) = (aux e1,aux e2,aux e3) in
+ (composeL [decl1;decl2;decl3], E_vector_subrange (e1,e2,e3))
)
; e_vector_update =
(fun (e1,e2,e3) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- (compose decl1 (compose decl2 decl3), E_vector_update (e1,e2,e3), b1 || b2)
+ let ((decl1,e1),(decl2,e2),(decl3,e3)) = (aux e1,aux e2,aux e3) in
+ (composeL [decl1;decl2;decl3], E_vector_update (e1,e2,e3))
)
; e_vector_update_subrange =
(fun (e1,e2,e3,e4) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- let (decl4,e4,b4) = aux e4 in
- (compose decl1 (compose decl2 (compose decl3 decl4)), E_vector_update_subrange (e1,e2,e3,e4),
- b1 || b2)
+ let ((decl1,e1),(decl2,e2),(decl3,e3),(decl4,e4)) = (aux e1,aux e2,aux e3,aux e4) in
+ (composeL [decl1;decl2;decl3;decl4], E_vector_update_subrange (e1,e2,e3,e4))
)
; e_vector_append =
(fun (e1,e2) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- (compose decl1 decl2, E_vector_append (e1,e2), b1 || b2)
- )
- ; e_list =
- (fun es ->
- let (decl,es,b) = list_aux es in
- (decl, E_list es,b)
+ let ((decl1,e1),(decl2,e2)) = (aux e1,aux e2) in
+ (compose decl1 decl2, E_vector_append (e1,e2))
)
+ ; e_list = (fun es -> let (decl,es) = list_aux es in (decl, E_list es))
; e_cons =
(fun (e1,e2) ->
- let (decl1,e1,b1) = aux e1 in
- let (decl2,e2,b2) = aux e2 in
- (compose decl1 decl2, E_cons (e1,e2), b1 || b2)
+ let ((decl1,e1),(decl2,e2)) = (aux e1,aux e2) in
+ (compose decl1 decl2, E_cons (e1,e2))
)
- ; e_record = (fun (decl,fexps,b) -> (decl, E_record fexps,b))
+ ; e_record = (fun (decl,fexps) -> (decl, E_record fexps))
; e_record_update =
- (fun (e1,(decl2,fexp,b2)) ->
- let (decl1,e1,b1) = aux e1 in
- (compose decl1 decl2, E_record_update (e1,fexp), b1 || b2)
- )
- ; e_field =
- (fun (e1,id) ->
- let (decl,e1,b) = aux e1 in
- (decl, E_field (e1,id),b)
+ (fun (e1,(decl2,fexp)) ->
+ let (decl1,e1) = aux e1 in
+ (compose decl1 decl2, E_record_update (e1,fexp))
)
- ; e_case =
- (fun (e1,pexps) ->
- let (decl,e1,b1) = aux e1 in
- let (pexps,b2) =
- List.fold_left
- (fun (acc,b_acc) (pat,b) -> (acc @ [pat], b_acc || b))
- ([],false) pexps in
- (decl, E_case (e1,pexps), b1 || b2)
- )
- ; e_let = (fun ((lb,b1),(exp,b2)) -> ((fun x -> x), E_let (lb,exp), b1 || b2))
+ ; e_field = (fun (e1,id) -> let (decl,e1) = aux e1 in (decl, E_field (e1,id)))
+ ; e_case = (fun (e1,pexps) -> let (decl,e1) = aux e1 in (decl, E_case (e1,pexps)))
+ ; e_let = (fun (lb,exp) -> ((fun x -> x), E_let (lb,exp)))
; e_assign =
(fun ((decl1,lexp),e2) ->
- let (decl2,e2,b2) = aux e2 in
- (compose decl1 decl2, E_assign (lexp,e2), b2)
+ let (decl2,e2) = aux e2 in
+ (compose decl1 decl2, E_assign (lexp,e2))
)
- ; e_exit = (fun e1 -> let (decl,e1,b) = aux e1 in (decl, E_exit e1,b))
- ; e_internal_cast = (fun (a,e1) -> let (decl,e1,b) = aux e1 in (decl, E_internal_cast (a,e1),b))
- ; e_internal_exp = (fun a -> ((fun x -> x), E_internal_exp a,false))
- ; e_internal_exp_user = (fun (a1,a2) -> ((fun x -> x), E_internal_exp_user (a1,a2),false))
+ ; e_exit = (fun e1 -> let (decl,e1) = aux e1 in (decl, E_exit e1))
+ ; e_internal_cast = (fun (a,e1) -> let (decl,e1) = aux e1 in (decl, E_internal_cast (a,e1)))
+ ; e_internal_exp = (fun a -> ((fun x -> x), E_internal_exp a))
+ ; e_internal_exp_user = (fun (a1,a2) -> ((fun x -> x), E_internal_exp_user (a1,a2)))
; e_internal_let =
(fun ((decl1,lexp), e2, e3) ->
- let (decl2,e2,b2) = aux e2 in
- let (decl3,e3,b3) = aux e3 in
- (compose decl1 (compose decl2 decl3), E_internal_let (lexp,e2,e3), b2 || b3)
+ let ((decl2,e2),(decl3,e3)) = (aux e2,aux e3) in
+ (composeL [decl1;decl2;decl3], E_internal_let (lexp,e2,e3))
)
- ; e_aux = (fun ((decl,e),annot) -> (decl,E_aux (e,annot)))
+ ; e_aux = (fun ((decl,e),annot) -> decl (E_aux (e,annot)))
; lEXP_id = (fun id -> ((fun x -> x), LEXP_id id))
- ; lEXP_memory =
- (fun (id,es) ->
- let (decl,es,_) = list_aux es in
- (decl, LEXP_memory (id,es))
- )
+ ; lEXP_memory = (fun (id,es) -> let (decl,es) = list_aux es in (decl, LEXP_memory (id,es)))
; lEXP_cast = (fun (typ,id) -> ((fun x -> x), LEXP_cast (typ,id)))
; lEXP_vector =
(fun ((decl1,lexp),e2) ->
- let (decl2,e2,_) = aux e2 in
+ let (decl2,e2) = aux e2 in
(compose decl1 decl2, LEXP_vector (lexp,e2))
)
; lEXP_vector_range =
(fun ((decl1,lexp),e2,e3) ->
- let (decl2,e2,_) = aux e2 in
- let (decl3,e3,_) = aux e3 in
- (compose decl1 (compose decl2 decl3), LEXP_vector_range (lexp,e2,e3))
+ let ((decl2,e2),(decl3,e3)) = (aux e2,aux e3) in
+ (composeL [decl1;decl2;decl3], LEXP_vector_range (lexp,e2,e3))
)
; lEXP_field = (fun ((decl,lexp),id) -> (decl, LEXP_field (lexp,id)))
; lEXP_aux = (fun ((decl,lexp),a) -> (decl,LEXP_aux (lexp,a)))
- ; fE_Fexp = (fun (id,e) -> let (decl,e,b) = aux e in (decl,FE_Fexp (id,e),b))
- ; fE_aux = (fun ((decl,fexp,b),annot) -> (decl, FE_aux (fexp,annot),b))
+ ; fE_Fexp = (fun (id,e) -> let (decl,e) = aux e in (decl,FE_Fexp (id,e)))
+ ; fE_aux = (fun ((decl,fexp),annot) -> (decl, FE_aux (fexp,annot)))
; fES_Fexps =
- (fun (fexps,bool) ->
- let (decl,fexps,b) =
- List.fold_left
- (fun (acc_decls,acc_fexps,acc_b) (decl,fexp,b) ->
- (compose acc_decls decl, acc_fexps @ [fexp], acc_b || b))
- ((fun x -> x), [], false) fexps in
- (decl, FES_Fexps (fexps,bool), b)
+ (fun (fexps,b) ->
+ let (decls,fexps) = List.split fexps in
+ (composeL decls, FES_Fexps (fexps,b))
)
- ; fES_aux = (fun ((decl,fexp,b),a) -> (decl, FES_aux (fexp,a), b))
- ; def_val_empty = ((fun x -> x), Def_val_empty,false)
- ; def_val_dec = (fun e -> let (decl,e,b) = aux e in (decl, Def_val_dec e, b))
- ; def_val_aux = (fun ((decl,defval,b),a) -> (decl, Def_val_aux (defval,a), b))
- ; pat_exp = (fun (pat,(e,b)) -> (Pat_exp (pat,e),b))
- ; pat_aux = (fun ((pexp,b),a) -> (Pat_aux (pexp,a),b))
- ; lB_val_explicit = (fun (typ,pat,(e,b)) -> (LB_val_explicit (typ,pat,e),b))
- ; lB_val_implicit = (fun (pat,(e,b)) -> (LB_val_implicit (pat,e),b))
- ; lB_aux = (fun ((lb,b),a) -> (LB_aux (lb,a),b))
+ ; fES_aux = (fun ((decl,fexp),a) -> (decl, FES_aux (fexp,a)))
+ ; def_val_empty = ((fun x -> x), Def_val_empty)
+ ; def_val_dec = (fun e -> let (decl,e) = aux e in (decl, Def_val_dec e))
+ ; def_val_aux = (fun ((decl,defval),a) -> (decl, Def_val_aux (defval,a)))
+ ; pat_exp = (fun (pat,e) -> Pat_exp (pat,e))
+ ; pat_aux = (fun (pexp,a) -> Pat_aux (pexp,a))
+ ; lB_val_explicit = (fun (typ,pat,e) -> LB_val_explicit (typ,pat,e))
+ ; lB_val_implicit = (fun (pat,e) -> LB_val_implicit (pat,e))
+ ; lB_aux = (fun (lb,a) -> LB_aux (lb,a))
; pat_alg = id_pat_alg
} exp
let rewrite_defs_sequentialise_effects (Defs defs) = rewrite_defs_base
- {rewrite_exp = (fun _ _ exp -> fst (sequentialise_effects exp));
+ {rewrite_exp = (fun _ _ exp -> sequentialise_effects exp);
rewrite_pat = rewrite_pat;
rewrite_let = rewrite_let;
rewrite_lexp = rewrite_lexp;