summaryrefslogtreecommitdiff
path: root/src/rewrites.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/rewrites.ml')
-rw-r--r--src/rewrites.ml102
1 files changed, 62 insertions, 40 deletions
diff --git a/src/rewrites.ml b/src/rewrites.ml
index 863f8115..063bbadb 100644
--- a/src/rewrites.ml
+++ b/src/rewrites.ml
@@ -385,7 +385,7 @@ let remove_vector_concat_pat pat =
let id_pat =
match typ_opt with
- | Some typ -> add_p_typ typ (P_aux (P_id child,cannot))
+ | Some typ -> add_p_typ env typ (P_aux (P_id child,cannot))
| None -> P_aux (P_id child,cannot) in
let letbind = fix_eff_lb (LB_aux (LB_val (id_pat,subv),cannot)) in
(letbind,
@@ -1552,7 +1552,7 @@ let rewrite_defs_early_return env (Defs defs) =
let eff = effect_of_annot tannot in
let tannot' = mk_tannot env typ (union_effects eff (mk_effect [BE_escape])) in
let exp' = match Env.get_ret_typ env with
- | Some typ -> add_e_cast typ exp
+ | Some typ -> add_e_cast env typ exp
| None -> exp in
E_aux (E_app (mk_id "early_return", [exp']), (l, tannot'))
| _ -> full_exp in
@@ -2110,15 +2110,12 @@ let rewrite_tuple_assignments env defs =
let env = env_of_annot annot in
match e_aux with
| E_assign (LEXP_aux (LEXP_tup lexps, _), exp) ->
- (* let _ = Pretty_print_common.print stderr (Pretty_print_sail.doc_exp (E_aux (e_aux, annot))) in *)
let (_, ids) = List.fold_left (fun (n, ids) _ -> (n + 1, ids @ [mk_id ("tup__" ^ string_of_int n)])) (0, []) lexps in
let block_assign i lexp = mk_exp (E_assign (strip_lexp lexp, mk_exp (E_id (mk_id ("tup__" ^ string_of_int i))))) in
let block = mk_exp (E_block (List.mapi block_assign lexps)) in
- let letbind = mk_letbind (mk_pat (P_typ (Type_check.typ_of exp,
- mk_pat (P_tup (List.map (fun id -> mk_pat (P_id id)) ids)))))
- (strip_exp exp)
- in
- let let_exp = mk_exp (E_let (letbind, block)) in
+ let pat = mk_pat (P_tup (List.map (fun id -> mk_pat (P_id id)) ids)) in
+ let exp' = add_e_cast env (typ_of exp) exp in
+ let let_exp = mk_exp (E_let (mk_letbind pat (strip_exp exp'), block)) in
begin
try check_exp env let_exp unit_typ with
| Type_error (_, l, err) ->
@@ -2159,9 +2156,11 @@ let rewrite_defs_remove_blocks env =
let l = get_loc_exp v in
let env = env_of v in
let typ = typ_of v in
- let wild = add_p_typ typ (annot_pat P_wild l env typ) in
+ let wild = annot_pat P_wild l env typ in
let e_aux = E_let (annot_letbind (unaux_pat wild, v) l env typ, body) in
- fix_eff_exp (annot_exp e_aux l env (typ_of body)) in
+ fix_eff_exp (annot_exp e_aux l env (typ_of body))
+ |> add_typs_let env typ (typ_of body)
+ in
let rec f l = function
| [] -> E_aux (E_lit (L_aux (L_unit,gen_loc l)), (simple_annot l unit_typ))
@@ -2192,19 +2191,20 @@ let letbind (v : 'a exp) (body : 'a exp -> 'a exp) : 'a exp =
| Some (env, typ, eff) when is_unit_typ typ ->
let body = body (annot_exp (E_lit (mk_lit L_unit)) l env unit_typ) in
let body_typ = try typ_of body with _ -> unit_typ in
- let wild = add_p_typ (typ_of v) (annot_pat P_wild l env (typ_of v)) in
+ let wild = annot_pat P_wild l env typ in
let lb = fix_eff_lb (annot_letbind (unaux_pat wild, v) l env unit_typ) in
fix_eff_exp (annot_exp (E_let (lb, body)) l env body_typ)
+ |> add_typs_let env typ body_typ
| Some (env, typ, eff) ->
let id = fresh_id "w__" l in
- let pat = add_p_typ (typ_of v) (annot_pat (P_id id) l env (typ_of v)) in
+ let pat = annot_pat (P_id id) l env typ in
let lb = fix_eff_lb (annot_letbind (unaux_pat pat, v) l env typ) in
let body = body (annot_exp (E_id id) l env typ) in
fix_eff_exp (annot_exp (E_let (lb, body)) l env (typ_of body))
+ |> add_typs_let env typ (typ_of body)
| None ->
raise (Reporting.err_unreachable l __POS__ "no type information")
-
let rec mapCont (f : 'b -> ('b -> 'a exp) -> 'a exp) (l : 'b list) (k : 'b list -> 'a exp) : 'a exp =
match l with
| [] -> k []
@@ -2241,9 +2241,9 @@ let rewrite_defs_letbind_effects env =
and n_pexp : 'b. bool -> 'a pexp -> ('a pexp -> 'b) -> 'b = fun newreturn pexp k ->
match pexp with
| Pat_aux (Pat_exp (pat,exp),annot) ->
- k (fix_eff_pexp (Pat_aux (Pat_exp (pat,n_exp_term newreturn exp), annot)))
+ k (fix_eff_pexp (Pat_aux (Pat_exp (pat, n_exp_term newreturn exp), annot)))
| Pat_aux (Pat_when (pat,guard,exp),annot) ->
- k (fix_eff_pexp (Pat_aux (Pat_when (pat,n_exp_term newreturn guard,n_exp_term newreturn exp), annot)))
+ k (fix_eff_pexp (Pat_aux (Pat_when (pat, n_exp_term newreturn guard, n_exp_term newreturn exp), annot)))
and n_pexpL (newreturn : bool) (pexps : 'a pexp list) (k : 'a pexp list -> 'a exp) : 'a exp =
mapCont (n_pexp newreturn) pexps k
@@ -2297,15 +2297,15 @@ let rewrite_defs_letbind_effects env =
and n_lexpL (lexps : 'a lexp list) (k : 'a lexp list -> 'a exp) : 'a exp =
mapCont n_lexp lexps k
- and n_exp_term (newreturn : bool) (exp : 'a exp) : 'a exp =
+ and n_exp_term ?cast:(cast=false) (newreturn : bool) (exp : 'a exp) : 'a exp =
let (E_aux (_,(l,tannot))) = exp in
let exp =
if newreturn then
(* let typ = try typ_of exp with _ -> unit_typ in *)
- let exp = add_e_cast (typ_of exp) exp in
+ let exp = if cast then add_e_cast (env_of exp) (typ_of exp) exp else exp in
annot_exp (E_internal_return exp) l (env_of exp) (typ_of exp)
- else
- exp in
+ else exp
+ in
(* n_exp_term forces an expression to be translated into a form
"let .. let .. let .. in EXP" where EXP has no effect and does not update
variables *)
@@ -2328,8 +2328,8 @@ let rewrite_defs_letbind_effects env =
(* Leave effectful operands of Boolean "and"/"or" in place to allow
short-circuiting. *)
let newreturn = effectful l || effectful r in
- let l = n_exp_term newreturn l in
- let r = n_exp_term newreturn r in
+ let l = n_exp_term ~cast:true newreturn l in
+ let r = n_exp_term ~cast:true newreturn r in
k (rewrap (E_app (op_bool, [l; r])))
| E_app (id,exps) ->
n_exp_nameL exps (fun exps ->
@@ -2348,7 +2348,8 @@ let rewrite_defs_letbind_effects env =
let newreturn = effectful exp2 || effectful exp3 in
let exp2 = n_exp_term newreturn exp2 in
let exp3 = n_exp_term newreturn exp3 in
- k (rewrap (E_if (exp1,exp2,exp3))) in
+ k (rewrap (E_if (exp1,exp2,exp3)))
+ in
if value exp1 then e_if (n_exp_term false exp1) else n_exp_name exp1 e_if
| E_for (id,start,stop,by,dir,body) ->
n_exp_name start (fun start ->
@@ -2362,7 +2363,7 @@ let rewrite_defs_letbind_effects env =
| Measure_aux (Measure_some exp,l) ->
Measure_aux (Measure_some (n_exp_term false exp),l)
in
- let cond = n_exp_term (effectful cond) cond in
+ let cond = n_exp_term ~cast:true (effectful cond) cond in
let body = n_exp_term (effectful body) body in
k (rewrap (E_loop (loop,measure,cond,body)))
| E_vector exps ->
@@ -2434,7 +2435,7 @@ let rewrite_defs_letbind_effects env =
| E_assert (exp1,exp2) ->
n_exp_name exp1 (fun exp1 ->
n_exp_name exp2 (fun exp2 ->
- k (rewrap (E_assert (exp1,exp2)))))
+ k (rewrap (E_assert (exp1, exp2)))))
| E_var (lexp,exp1,exp2) ->
n_lexp lexp (fun lexp ->
n_exp exp1 (fun exp1 ->
@@ -2502,7 +2503,7 @@ let rewrite_defs_internal_lets env =
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) -> add_p_typ typ (P_aux (P_id id, annot))
+ | LEXP_cast (typ, id) -> add_p_typ (env_of_annot annot) typ (P_aux (P_id id, annot))
| LEXP_tup lexps -> P_aux (P_tup (List.map pat_of_local_lexp lexps), annot)
| _ -> raise (Reporting.err_unreachable l __POS__ "unexpected local lexp") in
@@ -2521,7 +2522,7 @@ let rewrite_defs_internal_lets env =
| LEXP_aux (_,lexp_annot') -> lexp_annot'
| exception _ -> lannot)
in
- let rhs = add_e_cast ltyp (rhs exp) in
+ let rhs = add_e_cast (env_of exp) ltyp (rhs exp) in
E_let (LB_aux (LB_val (pat_of_local_lexp lhs, rhs), annot), body)
| LB_aux (LB_val (pat,exp'),annot') ->
if effectful exp'
@@ -2533,7 +2534,7 @@ let rewrite_defs_internal_lets env =
| LEXP_aux (LEXP_id id, annot) ->
(P_id id, annot)
| LEXP_aux (LEXP_cast (typ, id), annot) ->
- (unaux_pat (add_p_typ typ (P_aux (P_id id, annot))), annot)
+ (unaux_pat (add_p_typ (env_of_annot annot) typ (P_aux (P_id id, annot))), annot)
| _ -> failwith "E_var with unexpected lexp" in
if effectful exp1 then
E_internal_plet (P_aux (paux, annot), exp1, exp2)
@@ -3331,22 +3332,24 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let tuple_exp = function
| [] -> annot_exp (E_lit (mk_lit L_unit)) l env unit_typ
| [e] -> e
- | es -> annot_exp (E_tuple es) l env (tuple_typ (List.map typ_of es)) in
+ | es -> annot_exp (E_tuple es) l env (tuple_typ (List.map typ_of es))
+ in
let tuple_pat = function
| [] -> annot_pat P_wild l env unit_typ
| [pat] ->
let typ = typ_of_pat pat in
- add_p_typ typ pat
+ add_p_typ env typ pat
| pats ->
let typ = tuple_typ (List.map typ_of_pat pats) in
- add_p_typ typ (annot_pat (P_tup pats) l env typ) in
+ add_p_typ env typ (annot_pat (P_tup pats) l env typ)
+ in
let rec add_vars overwrite ((E_aux (expaux,annot)) as exp) vars =
match expaux with
| E_let (lb,exp) ->
let exp = add_vars overwrite exp vars in
- E_aux (E_let (lb,exp),swaptyp (typ_of exp) annot)
+ E_aux (E_let (lb,exp), swaptyp (typ_of exp) annot)
| E_var (lexp,exp1,exp2) ->
let exp2 = add_vars overwrite exp2 vars in
E_aux (E_var (lexp,exp1,exp2), swaptyp (typ_of exp2) annot)
@@ -3355,7 +3358,11 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
E_aux (E_internal_plet (pat,exp1,exp2), swaptyp (typ_of exp2) annot)
| E_internal_return exp2 ->
let exp2 = add_vars overwrite exp2 vars in
- E_aux (E_internal_return exp2,swaptyp (typ_of exp2) annot)
+ E_aux (E_internal_return exp2, swaptyp (typ_of exp2) annot)
+ | E_cast (typ, exp) ->
+ let (E_aux (expaux, annot) as exp) = add_vars overwrite exp vars in
+ let typ' = typ_of exp in
+ add_e_cast (env_of exp) typ' (E_aux (expaux, swaptyp typ' annot))
| _ ->
(* after rewrite_defs_letbind_effects there cannot be terms that have
effects/update local variables in "tail-position": check n_exp_term
@@ -3364,6 +3371,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let lb = LB_aux (LB_val (P_aux (P_wild, annot), exp), annot) in
let exp' = tuple_exp vars in
E_aux (E_let (lb, exp'), swaptyp (typ_of exp') annot)
+ |> add_typs_let env (typ_of exp) (typ_of exp')
else tuple_exp (exp :: vars) in
let mk_var_exps_pats l env ids =
@@ -3375,7 +3383,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
exp, P_aux (P_id id, a))
|> List.split in
- let rewrite used_vars (E_aux (expaux,((el,_) as annot)) as full_exp) (P_aux (paux,(pl,pannot)) as pat) =
+ let rec rewrite used_vars (E_aux (expaux,((el,_) as annot)) as full_exp) (P_aux (paux,(pl,pannot)) as pat) =
let env = env_of_annot annot in
let overwrite = match paux with
| P_wild | P_typ (_, P_aux (P_wild, _)) -> true
@@ -3414,11 +3422,15 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
in
let lvar_nc = nc_and (nc_lteq (nvar lower_kid) (nvar lvar_kid)) (nc_lteq (nvar lvar_kid) (nvar upper_kid)) in
let lvar_typ = mk_typ (Typ_exist (List.map (mk_kopt K_int) [lvar_kid], lvar_nc, atom_typ (nvar lvar_kid))) in
- let lvar_pat = unaux_pat (add_p_typ lvar_typ (annot_pat (P_var (
+ let lvar_pat = unaux_pat (annot_pat (P_var (
annot_pat (P_id id) el env (atom_typ (nvar lvar_kid)),
- TP_aux (TP_var lvar_kid, gen_loc el))) el env lvar_typ)) in
+ TP_aux (TP_var lvar_kid, gen_loc el))) el env lvar_typ)
+ in
let lb = fix_eff_lb (annot_letbind (lvar_pat, exp1) el env lvar_typ) in
- let body = fix_eff_exp (annot_exp (E_let (lb, exp4)) el env (typ_of exp4)) in
+ let body =
+ fix_eff_exp (annot_exp (E_let (lb, exp4)) el env (typ_of exp4))
+ |> add_typs_let env lvar_typ (typ_of exp4)
+ in
(* If lower > upper, the loop body never gets executed, and the type
checker might not be able to prove that the initial value exp1
satisfies the constraints on the loop variable.
@@ -3518,7 +3530,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
| E_assign (lexp,vexp) ->
let mk_id_pat id =
let typ = lvar_typ (Env.lookup_id id env) in
- add_p_typ typ (annot_pat (P_id id) pl env typ)
+ add_p_typ env typ (annot_pat (P_id id) pl env typ)
in
if effectful exp then
Same_vars (E_aux (E_assign (lexp,vexp),annot))
@@ -3528,7 +3540,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let pat = annot_pat (P_id id) pl env (typ_of vexp) in
Added_vars (vexp, mk_id_pat id)
| LEXP_aux (LEXP_cast (typ,id),annot) ->
- let pat = add_p_typ typ (annot_pat (P_id id) pl env (typ_of vexp)) in
+ let pat = add_p_typ env typ (annot_pat (P_id id) pl env (typ_of vexp)) in
Added_vars (vexp,pat)
| LEXP_aux (LEXP_vector (LEXP_aux (LEXP_id id,((l2,_) as annot2)),i),((l1,_) as annot)) ->
let eid = annot_exp (E_id id) l2 env (typ_of_annot annot2) in
@@ -3542,6 +3554,13 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let pat = annot_pat (P_id id) pl env (typ_of vexp) in
Added_vars (vexp,pat)
| _ -> Same_vars (E_aux (E_assign (lexp,vexp),annot)))
+ | E_cast (typ, exp) ->
+ begin match rewrite used_vars exp pat with
+ | Added_vars (exp', pat') ->
+ Added_vars (add_e_cast (env_of exp') (typ_of exp') exp', pat')
+ | Same_vars (exp') ->
+ Same_vars (E_aux (E_cast (typ, exp'), annot))
+ end
| _ ->
(* after rewrite_defs_letbind_effects this expression is pure and updates
no variables: check n_exp_term and where it's used. *)
@@ -3562,7 +3581,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
| LEXP_aux (LEXP_id id, _) ->
P_id id, typ_of v
| LEXP_aux (LEXP_cast (typ, id), _) ->
- unaux_pat (add_p_typ typ (annot_pat (P_id id) l env (typ_of v))), typ
+ unaux_pat (add_p_typ env typ (annot_pat (P_id id) l env (typ_of v))), typ
| _ ->
raise (Reporting.err_unreachable l __POS__
"E_var with a lexp that is not a variable") in
@@ -3576,6 +3595,9 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
rewrite_var_updates exp'
| E_internal_plet (pat,v,body) ->
failwith "rewrite_var_updates: E_internal_plet shouldn't be introduced yet"
+ | E_cast (typ, exp) ->
+ let exp' = rewrite_var_updates exp in
+ E_aux (E_cast (typ, exp'), annot)
(* There are no other expressions that have effects or variable updates in
"tail-position": check the definition nexp_term and where it is used. *)
| _ -> exp
@@ -3711,7 +3733,7 @@ let rewrite_defs_remove_superfluous_returns env =
let add_opt_cast typopt1 typopt2 annot exp =
match typopt1, typopt2 with
- | Some typ, _ | _, Some typ -> add_e_cast typ exp
+ | Some typ, _ | _, Some typ -> add_e_cast (env_of exp) typ exp
| None, None -> exp
in