summaryrefslogtreecommitdiff
path: root/src/rewrites.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/rewrites.ml')
-rw-r--r--src/rewrites.ml621
1 files changed, 366 insertions, 255 deletions
diff --git a/src/rewrites.ml b/src/rewrites.ml
index 7a085213..0ad4c56e 100644
--- a/src/rewrites.ml
+++ b/src/rewrites.ml
@@ -82,7 +82,7 @@ let fresh_id_pat pre ((l,annot)) =
let get_loc_exp (E_aux (_,(l,_))) = l
-let gen_vs (id, spec) = Initial_check.extern_of_string dec_ord (mk_id id) spec
+let gen_vs (id, spec) = Initial_check.extern_of_string (mk_id id) spec
let annot_exp_effect e_aux l env typ effect = E_aux (e_aux, (l, mk_tannot env typ effect))
let annot_exp e_aux l env typ = annot_exp_effect e_aux l env typ no_effect
@@ -169,16 +169,16 @@ let vector_string_to_bit_list l lit =
| 'D' -> ['1';'1';'0';'1']
| 'E' -> ['1';'1';'1';'0']
| 'F' -> ['1';'1';'1';'1']
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ "hexchar_to_binlist given unrecognized character") in
+ | _ -> raise (Reporting.err_unreachable l __POS__ "hexchar_to_binlist given unrecognized character") in
let s_bin = match lit with
| L_hex s_hex -> List.flatten (List.map hexchar_to_binlist (explode (String.uppercase_ascii s_hex)))
| L_bin s_bin -> explode s_bin
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ "s_bin given non vector literal") in
+ | _ -> raise (Reporting.err_unreachable l __POS__ "s_bin given non vector literal") in
List.map (function '0' -> L_aux (L_zero, gen_loc l)
| '1' -> L_aux (L_one, gen_loc l)
- | _ -> raise (Reporting_basic.err_unreachable (gen_loc l) __POS__ "binary had non-zero or one")) s_bin
+ | _ -> raise (Reporting.err_unreachable (gen_loc l) __POS__ "binary had non-zero or one")) s_bin
let find_used_vars exp =
(* Overapproximates the set of used identifiers, but for the use cases below
@@ -255,8 +255,8 @@ let rec rewrite_nexp_ids env (Nexp_aux (nexp, l) as nexp_aux) = match nexp with
let rewrite_defs_nexp_ids, rewrite_typ_nexp_ids =
let rec rewrite_typ env (Typ_aux (typ, l) as typ_aux) = match typ with
- | Typ_fn (arg_t, ret_t, eff) ->
- Typ_aux (Typ_fn (rewrite_typ env arg_t, rewrite_typ env ret_t, eff), l)
+ | Typ_fn (arg_ts, ret_t, eff) ->
+ Typ_aux (Typ_fn (List.map (rewrite_typ env) arg_ts, rewrite_typ env ret_t, eff), l)
| Typ_tup ts ->
Typ_aux (Typ_tup (List.map (rewrite_typ env) ts), l)
| Typ_exist (kids, c, typ) ->
@@ -264,13 +264,15 @@ let rewrite_defs_nexp_ids, rewrite_typ_nexp_ids =
| Typ_app (id, targs) ->
Typ_aux (Typ_app (id, List.map (rewrite_typ_arg env) targs), l)
| _ -> typ_aux
- and rewrite_typ_arg env (Typ_arg_aux (targ, l) as targ_aux) = match targ with
- | Typ_arg_nexp nexp ->
- Typ_arg_aux (Typ_arg_nexp (rewrite_nexp_ids env nexp), l)
- | Typ_arg_typ typ ->
- Typ_arg_aux (Typ_arg_typ (rewrite_typ env typ), l)
- | Typ_arg_order ord ->
- Typ_arg_aux (Typ_arg_order ord, l)
+ and rewrite_typ_arg env (A_aux (targ, l) as targ_aux) = match targ with
+ | A_nexp nexp ->
+ A_aux (A_nexp (rewrite_nexp_ids env nexp), l)
+ | A_typ typ ->
+ A_aux (A_typ (rewrite_typ env typ), l)
+ | A_order ord ->
+ A_aux (A_order ord, l)
+ | A_bool nc ->
+ A_aux (A_bool nc, l)
in
let rewrite_annot (l, tannot) =
@@ -409,7 +411,7 @@ let rewrite_sizeof (Defs defs) =
| P_id id | P_as (_, id) ->
let (Typ_aux (typ,_) as typ_aux) = typ_of_annot annot in
(match typ with
- | Typ_app (atom, [Typ_arg_aux (Typ_arg_nexp nexp, _)])
+ | Typ_app (atom, [A_aux (A_nexp nexp, _)])
when string_of_id atom = "atom" ->
[nexp, E_id id]
| Typ_app (vector, _) when string_of_id vector = "vector" ->
@@ -461,7 +463,7 @@ let rewrite_sizeof (Defs defs) =
let inst =
try instantiation_of orig_exp with
| Type_error (l, err) ->
- raise (Reporting_basic.err_typ l (Type_error.string_of_type_error err)) in
+ raise (Reporting.err_typ l (Type_error.string_of_type_error err)) in
(* Rewrite the inst using orig_kid so that each type variable has it's
original name rather than a mangled typechecker name *)
let inst = KBindings.fold (fun kid uvar b -> KBindings.add (orig_kid kid) uvar b) inst KBindings.empty in
@@ -470,17 +472,17 @@ let rewrite_sizeof (Defs defs) =
assert (not (Str.string_match ex_regex (string_of_kid kid) 0));
let uvar = try Some (KBindings.find (orig_kid kid) inst) with Not_found -> None in
match uvar with
- | Some (U_nexp nexp) ->
+ | Some (A_aux (A_nexp nexp, _)) ->
let sizeof = E_aux (E_sizeof nexp, (l, mk_tannot env (atom_typ nexp) no_effect)) in
(try rewrite_trivial_sizeof_exp sizeof with
| Type_error (l, err) ->
- raise (Reporting_basic.err_typ l (Type_error.string_of_type_error err)))
+ raise (Reporting.err_typ l (Type_error.string_of_type_error err)))
(* If the type variable is Not_found then it was probably
introduced by a P_var pattern, so it likely exists as
a variable in scope. It can't be an existential because the assert rules that out. *)
| None -> annot_exp (E_id (id_of_kid (orig_kid kid))) l env (atom_typ (nvar (orig_kid kid)))
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
("failed to infer nexp for type variable " ^ string_of_kid kid ^
" of function " ^ string_of_id f))
end in
@@ -513,8 +515,8 @@ let rewrite_sizeof (Defs defs) =
; e_vector_append = (fun ((e1,e1'),(e2,e2')) -> (E_vector_append (e1,e2), E_vector_append (e1',e2')))
; e_list = (fun es -> let (es, es') = List.split es in (E_list es, E_list es'))
; e_cons = (fun ((e1,e1'),(e2,e2')) -> (E_cons (e1,e2), E_cons (e1',e2')))
- ; e_record = (fun (fexps, fexps') -> (E_record fexps, E_record fexps'))
- ; e_record_update = (fun ((e1,e1'),(fexp,fexp')) -> (E_record_update (e1,fexp), E_record_update (e1',fexp')))
+ ; e_record = (fun fexps -> let (fexps, fexps') = List.split fexps in (E_record fexps, E_record fexps'))
+ ; e_record_update = (fun ((e1,e1'),fexps) -> let (fexps, fexps') = List.split fexps in (E_record_update (e1,fexps), E_record_update (e1',fexps')))
; e_field = (fun ((e1,e1'),id) -> (E_field (e1,id), E_field (e1',id)))
; e_case = (fun ((e1,e1'),pexps) -> let (pexps, pexps') = List.split pexps in (E_case (e1,pexps), E_case (e1',pexps')))
; e_try = (fun ((e1,e1'),pexps) -> let (pexps, pexps') = List.split pexps in (E_try (e1,pexps), E_try (e1',pexps')))
@@ -543,8 +545,6 @@ let rewrite_sizeof (Defs defs) =
; lEXP_aux = (fun ((lexp,lexp'),annot) -> (LEXP_aux (lexp,annot), LEXP_aux (lexp',annot)))
; fE_Fexp = (fun (id,(e,e')) -> (FE_Fexp (id,e), FE_Fexp (id,e')))
; fE_aux = (fun ((fexp,fexp'),annot) -> (FE_aux (fexp,annot), FE_aux (fexp',annot)))
- ; fES_Fexps = (fun (fexps,b) -> let (fexps, fexps') = List.split fexps in (FES_Fexps (fexps,b), FES_Fexps (fexps',b)))
- ; fES_aux = (fun ((fexp,fexp'),annot) -> (FES_aux (fexp,annot), FES_aux (fexp',annot)))
; def_val_empty = (Def_val_empty, Def_val_empty)
; def_val_dec = (fun (e,e') -> (Def_val_dec e, Def_val_dec e'))
; def_val_aux = (fun ((defval,defval'),aux) -> (Def_val_aux (defval,aux), Def_val_aux (defval',aux)))
@@ -592,7 +592,7 @@ let rewrite_sizeof (Defs defs) =
let penv = env_of_annot pannot in
let peff = effect_of_annot (snd pannot) in
if KidSet.is_empty nvars then paux else
- match pat_typ_of paux with
+ match typ_of_pat paux with
| Typ_aux (Typ_tup typs, _) ->
let ptyp' = Typ_aux (Typ_tup (kid_typs @ typs), l) in
(match pat with
@@ -605,10 +605,10 @@ let rewrite_sizeof (Defs defs) =
| P_as (_, id) | P_id id ->
(* adding parameters here would change the type of id;
we should remove the P_as/P_id here and add a let-binding to the body *)
- raise (Reporting_basic.err_todo l
+ raise (Reporting.err_todo l
"rewriting as- or id-patterns for sizeof expressions not yet implemented")
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"unexpected pattern while rewriting function parameters for sizeof expressions"))
| ptyp ->
let ptyp' = Typ_aux (Typ_tup (kid_typs @ [ptyp]), l) in
@@ -649,6 +649,9 @@ let rewrite_sizeof (Defs defs) =
LB_val (pat, exp') in
(params_map, defs @ [DEF_val (LB_aux (lb', annot))])
end
+ | DEF_reg_dec (DEC_aux (DEC_config (id, typ, exp), annot)) ->
+ let exp' = fst (fold_exp { copy_exp_alg with e_aux = e_app_aux params_map } exp) in
+ (params_map, defs @ [DEF_reg_dec (DEC_aux (DEC_config (id, typ, exp'), annot))])
| def ->
(params_map, defs @ [def]) in
@@ -658,16 +661,10 @@ let rewrite_sizeof (Defs defs) =
let kid_typs = List.map (fun kid -> atom_typ (nvar kid))
(KidSet.elements (Bindings.find id params_map)) in
let typ' = match typ with
- | Typ_aux (Typ_fn (vtyp_arg, vtyp_ret, declared_eff), vl) ->
- let vtyp_arg' = begin
- match vtyp_arg with
- | Typ_aux (Typ_tup typs, vl) ->
- Typ_aux (Typ_tup (kid_typs @ typs), vl)
- | _ -> Typ_aux (Typ_tup (kid_typs @ [vtyp_arg]), vl)
- end in
- Typ_aux (Typ_fn (vtyp_arg', vtyp_ret, declared_eff), vl)
+ | Typ_aux (Typ_fn (vtyp_args, vtyp_ret, declared_eff), vl) ->
+ Typ_aux (Typ_fn (kid_typs @ vtyp_args, vtyp_ret, declared_eff), vl)
| _ ->
- raise (Reporting_basic.err_typ l "val spec with non-function type") in
+ raise (Reporting.err_typ l "val spec with non-function type") in
TypSchm_aux (TypSchm_ts (tq, typ'), l)
else ts in
match def with
@@ -764,7 +761,7 @@ let remove_vector_concat_pat pat =
P_aux (P_app (id, List.map aux pats), a)
| _ ->
raise
- (Reporting_basic.err_unreachable
+ (Reporting.err_unreachable
l __POS__ "name_vector_concat_elements: Non-vector in vector-concat pattern") in
P_vector_concat (List.map aux pats) in
{id_pat_alg with p_vector_concat = p_vector_concat} in
@@ -812,7 +809,7 @@ let remove_vector_concat_pat pat =
then Big_int.sub (Big_int.add start length) (Big_int.of_int 1)
else Big_int.add (Big_int.sub start length) (Big_int.of_int 1))
| _ ->
- raise (Reporting_basic.err_unreachable (fst rannot') __POS__
+ raise (Reporting.err_unreachable (fst rannot') __POS__
("unname_vector_concat_elements: vector of unspecified length in vector-concat pattern"))) in
let rec aux typ_opt (pos,pat_acc,decl_acc) (P_aux (p,cannot),is_last) =
let ctyp = Env.base_typ_of (env_of_annot cannot) (typ_of_annot cannot) in
@@ -826,7 +823,7 @@ let remove_vector_concat_pat pat =
if is_last then (pos,last_idx)
else
raise
- (Reporting_basic.err_unreachable
+ (Reporting.err_unreachable
l __POS__ ("unname_vector_concat_elements: vector of unspecified length in vector-concat pattern")) in
(match p with
(* if we see a named vector pattern, remove the name and remember to
@@ -936,7 +933,7 @@ let remove_vector_concat_pat pat =
| _, _ ->
(*if is_last then*) acc @ [wild Big_int.zero]
else raise
- (Reporting_basic.err_unreachable l __POS__
+ (Reporting.err_unreachable l __POS__
("remove_vector_concats: Non-vector in vector-concat pattern " ^
string_of_typ (typ_of_annot annot))) in
@@ -1162,11 +1159,11 @@ let subst_id_exp exp (id1,id2) =
let rec pat_to_exp ((P_aux (pat,(l,annot))) as p_aux) =
let rewrap e = E_aux (e,(l,annot)) in
- let env = pat_env_of p_aux in
- let typ = pat_typ_of p_aux in
+ let env = env_of_pat p_aux in
+ let typ = typ_of_pat p_aux in
match pat with
| P_lit lit -> rewrap (E_lit lit)
- | P_wild -> raise (Reporting_basic.err_unreachable l __POS__
+ | P_wild -> raise (Reporting.err_unreachable l __POS__
"pat_to_exp given wildcard pattern")
| P_or(pat1, pat2) -> (* todo: insert boolean or *) pat_to_exp pat1
| P_not(pat) -> (* todo: insert boolean not *) pat_to_exp pat
@@ -1176,7 +1173,7 @@ let rec pat_to_exp ((P_aux (pat,(l,annot))) as p_aux) =
| P_id id -> rewrap (E_id id)
| P_app (id,pats) -> rewrap (E_app (id, List.map pat_to_exp pats))
| P_record (fpats,b) ->
- rewrap (E_record (FES_aux (FES_Fexps (List.map fpat_to_fexp fpats,b),(l,annot))))
+ rewrap (E_record (List.map fpat_to_fexp fpats))
| P_vector pats -> rewrap (E_vector (List.map pat_to_exp pats))
| P_vector_concat pats -> begin
let empty_vec = E_aux (E_vector [], (l,())) in
@@ -1254,7 +1251,7 @@ let rewrite_guarded_clauses l cs =
| ((pat,guard,body,annot) as c) :: cs ->
group_aux (remove_wildcards "g__" pat, [c], annot) [] cs
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"group given empty list in rewrite_guarded_clauses") in
let add_group cs groups = (if_pexp (groups @ fallthrough) cs) :: groups in
List.fold_right add_group groups []
@@ -1266,7 +1263,7 @@ let rewrite_guarded_clauses l cs =
let (Pat_aux (_,annot)) = pexp in
(pat, body, annot)
| [] ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"if_pexp given empty list in rewrite_guarded_clauses"))
and if_exp fallthrough current_pat = (function
| (pat,guard,body,annot) :: ((pat',guard',body',annot') as c') :: cs ->
@@ -1290,7 +1287,7 @@ let rewrite_guarded_clauses l cs =
fix_eff_exp (annot_exp (E_if (exp,body,else_exp)) (fst annot) (env_of exp) (typ_of body))
| _, _ -> body)
| [] ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"if_exp given empty list in rewrite_guarded_clauses")) in
group [] cs
@@ -1328,7 +1325,7 @@ let contains_bitvector_pexp = function
let remove_bitvector_pat (P_aux (_, (l, _)) as pat) =
- let env = try pat_env_of pat with _ -> Env.empty in
+ let env = try env_of_pat pat with _ -> Env.empty in
(* first introduce names for bitvector patterns *)
let name_bitvector_roots =
@@ -1366,7 +1363,7 @@ let remove_bitvector_pat (P_aux (_, (l, _)) as pat) =
} in
let pat, env = bind_pat_no_guard env
(strip_pat ((fold_pat name_bitvector_roots pat) false))
- (pat_typ_of pat) in
+ (typ_of_pat pat) in
(* Then collect guard expressions testing whether the literal bits of a
bitvector pattern match those of a given bitvector, and collect let
@@ -1425,7 +1422,7 @@ let remove_bitvector_pat (P_aux (_, (l, _)) as pat) =
let start_idx = match start with
| Nexp_aux (Nexp_constant s, _) -> s
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"guard_bitvector_pat called on pattern with non-constant start index") in
let add_bit_pat (idx, current, guards, dls) pat =
let idx' =
@@ -1613,7 +1610,7 @@ let rewrite_defs_remove_numeral_pats =
fold_pat { (compute_pat_alg None compose_guard_opt) with p_lit = p_lit outer_env } in
let pat_aux (pexp_aux, a) =
let pat,guard,exp,a = destruct_pexp (Pat_aux (pexp_aux, a)) in
- let guard',pat = guard_pat (pat_env_of pat) pat in
+ let guard',pat = guard_pat (env_of_pat pat) pat in
match compose_guard_opt guard guard' with
| Some g -> Pat_aux (Pat_when (pat, g, exp), a)
| None -> Pat_aux (Pat_exp (pat, exp), a) in
@@ -1731,17 +1728,18 @@ let rec rewrite_lexp_to_rhs ((LEXP_aux(lexp,((l,_) as annot))) as le) =
let env = env_of_annot lannot in
match Env.expand_synonyms env (typ_of_annot lannot) with
| Typ_aux (Typ_id rectyp_id, _) | Typ_aux (Typ_app (rectyp_id, _), _) when Env.is_record rectyp_id env ->
- let field_update exp = FES_aux (FES_Fexps ([FE_aux (FE_Fexp (id, exp), annot)], false), annot) in
- (lhs, (fun exp -> rhs (E_aux (E_record_update (lexp_to_exp lexp, field_update exp), lannot))))
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ ("Unsupported lexp: " ^ string_of_lexp le))
+ let field_update exp = FE_aux (FE_Fexp (id, exp), annot) in
+ (lhs, (fun exp -> rhs (E_aux (E_record_update (lexp_to_exp lexp, [field_update exp]), lannot))))
+ | _ -> raise (Reporting.err_unreachable l __POS__ ("Unsupported lexp: " ^ string_of_lexp le))
end
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ ("Unsupported lexp: " ^ string_of_lexp le))
+ | _ -> raise (Reporting.err_unreachable l __POS__ ("Unsupported lexp: " ^ string_of_lexp le))
let updates_vars exp =
let e_assign ((_, lexp), (u, exp)) =
(u || lexp_is_local lexp (env_of exp), E_assign (lexp, exp)) in
fst (fold_exp { (compute_exp_alg false (||)) with e_assign = e_assign } exp)
+
(*Expects to be called after rewrite_defs; thus the following should not appear:
internal_exp of any form
lit vectors in patterns or expressions
@@ -1765,72 +1763,18 @@ let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as f
let effects = union_eff_exps exps' in
let block = E_aux (E_block exps', (gen_loc l, mk_tannot env unit_typ effects)) in
[fix_eff_exp (E_aux (E_var(le', e', block), annot))]
- (*| ((E_aux(E_if(c,t,e),(l,annot))) as exp)::exps ->
- let vars_t = introduced_variables t in
- let vars_e = introduced_variables e in
- let new_vars = Envmap.intersect vars_t vars_e in
- if Envmap.is_empty new_vars
- then (rewrite_base exp)::walker exps
- else
- let new_nmap = match nmap with
- | None -> Some(Nexpmap.empty,new_vars)
- | Some(nm,s) -> Some(nm, Envmap.union new_vars s) in
- let c' = rewrite_base c in
- let t' = rewriters.rewrite_exp rewriters new_nmap t in
- let e' = rewriters.rewrite_exp rewriters new_nmap e in
- let exps' = walker exps in
- fst ((Envmap.fold
- (fun (res,effects) i (t,e) ->
- let bitlit = E_aux (E_lit (L_aux(L_zero, Parse_ast.Generated l)),
- (Parse_ast.Generated l, simple_annot bit_t)) in
- let rangelit = E_aux (E_lit (L_aux (L_num 0, Parse_ast.Generated l)),
- (Parse_ast.Generated l, simple_annot nat_t)) in
- let set_exp =
- match t.t with
- | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) -> bitlit
- | Tapp("range", _) | Tapp("atom", _) -> rangelit
- | Tapp("vector", [_;_;_;TA_typ ( {t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})})])
- | Tapp(("reg"|"register"),[TA_typ ({t = Tapp("vector",
- [_;_;_;TA_typ ( {t=Tid "bit"}
- | {t=Tabbrev(_,{t=Tid "bit"})})])})])
- | Tabbrev(_,{t = Tapp("vector",
- [_;_;_;TA_typ ( {t=Tid "bit"}
- | {t=Tabbrev(_,{t=Tid "bit"})})])}) ->
- E_aux (E_vector_indexed([], Def_val_aux(Def_val_dec bitlit,
- (Parse_ast.Generated l,simple_annot bit_t))),
- (Parse_ast.Generated l, simple_annot t))
- | _ -> e in
- let unioneffs = union_effects effects (get_effsum_exp set_exp) in
- ([E_aux (E_var (LEXP_aux (LEXP_id (Id_aux (Id i, Parse_ast.Generated l)),
- (Parse_ast.Generated l, (tag_annot t Emp_intro))),
- set_exp,
- E_aux (E_block res, (Parse_ast.Generated l, (simple_annot_efr unit_t effects)))),
- (Parse_ast.Generated l, simple_annot_efr unit_t unioneffs))],unioneffs)))
- (E_aux(E_if(c',t',e'),(Parse_ast.Generated l, annot))::exps',eff_union_exps (c'::t'::e'::exps')) new_vars)*)
| e::exps -> (rewrite_rec e)::(walker exps)
in
- check_exp (env_of full_exp)
- (E_aux (E_block (List.map strip_exp (walker exps)), (l, ()))) (typ_of full_exp)
+ E_aux (E_block (walker exps), annot)
+
| E_assign(le,e)
when lexp_is_local_intro le (env_of full_exp) && not (lexp_is_effectful le) ->
let (le', re') = rewrite_lexp_to_rhs le in
let e' = re' (rewrite_base e) in
let block = annot_exp (E_block []) (gen_loc l) (env_of full_exp) unit_typ in
- check_exp (env_of full_exp)
- (strip_exp (E_aux (E_var(le', e', block), annot))) (typ_of full_exp)
- | _ -> rewrite_base full_exp
-
-(*let rewrite_lexp_lift_assign_intro rewriters ((LEXP_aux(lexp,annot)) as le) =
- let rewrap le = LEXP_aux(le,annot) in
- let rewrite_base = rewrite_lexp rewriters in
- match lexp, annot with
- | (LEXP_id id | LEXP_cast (_,id)), (l, Some (env, typ, eff)) ->
- (match Env.lookup_id id env with
- | Unbound | Local _ ->
- LEXP_aux (lexp, (l, Some (env, typ, union_effects eff (mk_effect [BE_lset]))))
- | _ -> rewrap lexp)
- | _ -> rewrite_base le*)
+ E_aux (E_var (le', e', block), annot)
+ | _ -> rewrite_base full_exp
let rewrite_defs_exp_lift_assign defs = rewrite_defs_base
{rewrite_exp = rewrite_exp_lift_assign_intro;
@@ -1872,56 +1816,6 @@ let rewrite_register_ref_writes (Defs defs) =
| [] -> [] in
Defs (rewrite (write_reg_spec @ defs))
- (* rewrite_defs_base { rewriters_base with rewrite_exp = rewrite_exp }
- (Defs (write_reg_spec @ defs)) *)
-
-
-(*let rewrite_exp_separate_ints rewriters ((E_aux (exp,((l,_) as annot))) as full_exp) =
- (*let tparms,t,tag,nexps,eff,cum_eff,bounds = match annot with
- | Base((tparms,t),tag,nexps,eff,cum_eff,bounds) -> tparms,t,tag,nexps,eff,cum_eff,bounds
- | _ -> [],unit_t,Emp_local,[],pure_e,pure_e,nob in*)
- let rewrap e = E_aux (e,annot) in
- (*let rewrap_effects e effsum =
- E_aux (e,(l,Base ((tparms,t),tag,nexps,eff,effsum,bounds))) in*)
- let rewrite_rec = rewriters.rewrite_exp rewriters in
- let rewrite_base = rewrite_exp rewriters in
- match exp with
- | E_lit (L_aux (((L_num _) as lit),_)) ->
- (match (is_within_machine64 t nexps) with
- | Yes -> let _ = Printf.eprintf "Rewriter of num_const, within 64bit int yes\n" in rewrite_base full_exp
- | Maybe -> let _ = Printf.eprintf "Rewriter of num_const, within 64bit int maybe\n" in rewrite_base full_exp
- | No -> let _ = Printf.eprintf "Rewriter of num_const, within 64bit int no\n" in E_aux(E_app(Id_aux (Id "integer_of_int",l),[rewrite_base full_exp]),
- (l, Base((tparms,t),External(None),nexps,eff,cum_eff,bounds))))
- | E_cast (typ, exp) -> rewrap (E_cast (typ, rewrite_rec exp))
- | E_app (id,exps) -> rewrap (E_app (id,List.map rewrite_rec exps))
- | E_app_infix(el,id,er) -> rewrap (E_app_infix(rewrite_rec el,id,rewrite_rec er))
- | E_for (id, e1, e2, e3, o, body) ->
- rewrap (E_for (id, rewrite_rec e1, rewrite_rec e2, rewrite_rec e3, o, rewrite_rec body))
- | E_vector_access (vec,index) -> rewrap (E_vector_access (rewrite_rec vec,rewrite_rec index))
- | E_vector_subrange (vec,i1,i2) ->
- rewrap (E_vector_subrange (rewrite_rec vec,rewrite_rec i1,rewrite_rec i2))
- | E_vector_update (vec,index,new_v) ->
- rewrap (E_vector_update (rewrite_rec vec,rewrite_rec index,rewrite_rec new_v))
- | E_vector_update_subrange (vec,i1,i2,new_v) ->
- rewrap (E_vector_update_subrange (rewrite_rec vec,rewrite_rec i1,rewrite_rec i2,rewrite_rec new_v))
- | E_case (exp ,pexps) ->
- rewrap (E_case (rewrite_rec exp,
- (List.map
- (fun (Pat_aux (Pat_exp(p,e),pannot)) ->
- Pat_aux (Pat_exp(rewriters.rewrite_pat rewriters nmap p,rewrite_rec e),pannot)) pexps)))
- | E_let (letbind,body) -> rewrap (E_let(rewriters.rewrite_let rewriters nmap letbind,rewrite_rec body))
- | E_var (lexp,exp,body) ->
- rewrap (E_var (rewriters.rewrite_lexp rewriters nmap lexp, rewrite_rec exp, rewrite_rec body))
- | _ -> rewrite_base full_exp
-
-let rewrite_defs_separate_numbs defs = rewrite_defs_base
- {rewrite_exp = rewrite_exp_separate_ints;
- rewrite_pat = rewrite_pat;
- rewrite_let = rewrite_let; (*will likely need a new one?*)
- rewrite_lexp = rewrite_lexp; (*will likely need a new one?*)
- rewrite_fun = rewrite_fun;
- rewrite_def = rewrite_def;
- rewrite_defs = rewrite_defs_base} defs*)
(* Remove redundant return statements, and translate remaining ones into an
(effectful) call to builtin function "early_return" (in the Lem shallow
@@ -2099,7 +1993,7 @@ let rewrite_defs_early_return (Defs defs) =
let swaptyp typ (l,tannot) = match destruct_tannot tannot with
| Some (env, typ', eff) -> (l, mk_tannot env typ eff)
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ "swaptyp called with empty type annotation")
+ | _ -> raise (Reporting.err_unreachable l __POS__ "swaptyp called with empty type annotation")
let is_funcl_rec (FCL_aux (FCL_Funcl (id, pexp), _)) =
let pat,guard,exp,pannot = destruct_pexp pexp in
@@ -2137,9 +2031,13 @@ let rewrite_split_fun_constr_pats fun_name (Defs defs) =
let pat, guard, exp, annot = destruct_pexp pexp in
match pat with
| P_aux (P_app (constr_id, args), pannot) ->
- let argstup_typ = tuple_typ (List.map pat_typ_of args) in
+ let argstup_typ = tuple_typ (List.map typ_of_pat args) in
let pannot' = swaptyp argstup_typ pannot in
- let pat' = P_aux (P_tup args, pannot') in
+ let pat' =
+ match args with
+ | [arg] -> arg
+ | _ -> P_aux (P_tup args, pannot')
+ in
let pexp' = construct_pexp (pat', guard, exp, annot) in
let aux_fun_id = prepend_id (fun_name ^ "_") constr_id in
let aux_funcl = FCL_aux (FCL_Funcl (aux_fun_id, pexp'), pannot') in
@@ -2174,9 +2072,9 @@ let rewrite_split_fun_constr_pats fun_name (Defs defs) =
let env, args_typ, ret_typ = match funcls with
| FCL_aux (FCL_Funcl (_, pexp), _) :: _ ->
let pat, _, exp, _ = destruct_pexp pexp in
- env_of exp, pat_typ_of pat, typ_of exp
+ env_of exp, typ_of_pat pat, typ_of exp
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"rewrite_split_fun_constr_pats: empty auxiliary function")
in
let eff = List.fold_left
@@ -2185,12 +2083,20 @@ let rewrite_split_fun_constr_pats fun_name (Defs defs) =
union_effects eff (effect_of exp))
no_effect funcls
in
- let fun_typ = function_typ args_typ ret_typ eff in
+ let fun_typ =
+ (* Because we got the argument type from a pattern we need to
+ do this. *)
+ match args_typ with
+ | Typ_aux (Typ_tup (args_typs), _) ->
+ function_typ args_typs ret_typ eff
+ | _ ->
+ function_typ [args_typ] ret_typ eff
+ in
let quant_new_tyvars qis =
let quant_tyvars = List.fold_left KidSet.union KidSet.empty (List.map tyvars_of_quant_item qis) in
let typ_tyvars = tyvars_of_typ fun_typ in
let new_tyvars = KidSet.diff typ_tyvars quant_tyvars in
- List.map (mk_qi_id BK_int) (KidSet.elements new_tyvars)
+ List.map (mk_qi_id K_int) (KidSet.elements new_tyvars)
in
let typquant = match typquant with
| TypQ_aux (TypQ_tq qis, l) ->
@@ -2202,7 +2108,7 @@ let rewrite_split_fun_constr_pats fun_name (Defs defs) =
in
TypQ_aux (TypQ_tq qis, l)
| _ ->
- TypQ_aux (TypQ_tq (List.map (mk_qi_id BK_int) (KidSet.elements (tyvars_of_typ fun_typ))), l)
+ TypQ_aux (TypQ_tq (List.map (mk_qi_id K_int) (KidSet.elements (tyvars_of_typ fun_typ))), l)
in
let val_spec =
VS_aux (VS_val_spec
@@ -2236,7 +2142,7 @@ let rewrite_fix_val_specs (Defs defs) =
begin
try Env.get_val_spec id env with
| _ ->
- raise (Reporting_basic.err_unreachable (Parse_ast.Unknown) __POS__
+ raise (Reporting.err_unreachable (Parse_ast.Unknown) __POS__
("No val spec found for " ^ string_of_id id))
end
in
@@ -2283,7 +2189,7 @@ let rewrite_fix_val_specs (Defs defs) =
type synonyms nested in existentials might cause problems).
A more robust solution would be to make the (global) environment
more easily available to the pretty-printer. *)
- let args_t' = Env.expand_synonyms (env_of exp) args_t in
+ let args_t' = List.map (Env.expand_synonyms (env_of exp)) args_t in
let ret_t' = Env.expand_synonyms (env_of exp) ret_t in
(tq, Typ_aux (Typ_fn (args_t', ret_t', eff'), a)), eff'
| _ -> assert false (* find_vs must return a function type *)
@@ -2298,9 +2204,11 @@ let rewrite_fix_val_specs (Defs defs) =
(* Repeat once to cross-propagate effects between clauses *)
let (val_specs, funcls) = List.fold_left rewrite_funcl (val_specs, []) funcls in
let recopt =
- if List.exists is_funcl_rec funcls then
- Rec_aux (Rec_rec, Parse_ast.Unknown)
- else recopt
+ match recopt with
+ | Rec_aux ((Rec_rec | Rec_measure _), _) -> recopt
+ | _ when List.exists is_funcl_rec funcls ->
+ Rec_aux (Rec_rec, Parse_ast.Unknown)
+ | _ -> recopt
in
let tannotopt = match tannotopt, funcls with
| Typ_annot_opt_aux (Typ_annot_opt_some (typq, typ), l),
@@ -2396,9 +2304,10 @@ let rewrite_constraint =
let rewrite_type_union_typs rw_typ (Tu_aux (Tu_ty_id (typ, id), annot)) =
Tu_aux (Tu_ty_id (rw_typ typ, id), annot)
-let rewrite_type_def_typs rw_typ rw_typquant rw_typschm (TD_aux (td, annot)) =
+let rewrite_type_def_typs rw_typ rw_typquant (TD_aux (td, annot)) =
match td with
- | TD_abbrev (id, nso, typschm) -> TD_aux (TD_abbrev (id, nso, rw_typschm typschm), annot)
+ | TD_abbrev (id, typq, A_aux (A_typ typ, l)) ->
+ TD_aux (TD_abbrev (id, rw_typquant typq, A_aux (A_typ (rw_typ typ), l)), annot)
| TD_record (id, nso, typq, typ_ids, flag) ->
TD_aux (TD_record (id, nso, rw_typquant typq, List.map (fun (typ, id) -> (rw_typ typ, id)) typ_ids, flag), annot)
| TD_variant (id, nso, typq, tus, flag) ->
@@ -2450,20 +2359,20 @@ let rewrite_undefined_if_gen always_bitvector defs =
let rec simple_typ (Typ_aux (typ_aux, l) as typ) = Typ_aux (simple_typ_aux typ_aux, l)
and simple_typ_aux = function
| Typ_id id -> Typ_id id
- | Typ_app (id, [_; _; Typ_arg_aux (Typ_arg_typ typ, l)]) when Id.compare id (mk_id "vector") = 0 ->
- Typ_app (mk_id "list", [Typ_arg_aux (Typ_arg_typ (simple_typ typ), l)])
+ | Typ_app (id, [_; _; A_aux (A_typ typ, l)]) when Id.compare id (mk_id "vector") = 0 ->
+ Typ_app (mk_id "list", [A_aux (A_typ (simple_typ typ), l)])
| Typ_app (id, [_]) when Id.compare id (mk_id "atom") = 0 ->
Typ_id (mk_id "int")
| Typ_app (id, [_; _]) when Id.compare id (mk_id "range") = 0 ->
Typ_id (mk_id "int")
| Typ_app (id, args) -> Typ_app (id, List.concat (List.map simple_typ_arg args))
- | Typ_fn (typ1, typ2, effs) -> Typ_fn (simple_typ typ1, simple_typ typ2, effs)
+ | Typ_fn (arg_typs, ret_typ, effs) -> Typ_fn (List.map simple_typ arg_typs, simple_typ ret_typ, effs)
| Typ_tup typs -> Typ_tup (List.map simple_typ typs)
| Typ_exist (_, _, Typ_aux (typ, l)) -> simple_typ_aux typ
| typ_aux -> typ_aux
-and simple_typ_arg (Typ_arg_aux (typ_arg_aux, l)) =
+and simple_typ_arg (A_aux (typ_arg_aux, l)) =
match typ_arg_aux with
- | Typ_arg_typ typ -> [Typ_arg_aux (Typ_arg_typ (simple_typ typ), l)]
+ | A_typ typ -> [A_aux (A_typ (simple_typ typ), l)]
| _ -> []
(* This pass aims to remove all the Num quantifiers from the specification. *)
@@ -2492,7 +2401,7 @@ let rewrite_simple_types (Defs defs) =
in
let simple_def = function
| DEF_spec vs -> DEF_spec (simple_vs vs)
- | DEF_type td -> DEF_type (rewrite_type_def_typs simple_typ simple_typquant simple_typschm td)
+ | DEF_type td -> DEF_type (rewrite_type_def_typs simple_typ simple_typquant td)
| DEF_reg_dec ds -> DEF_reg_dec (rewrite_dec_spec_typs simple_typ ds)
| def -> def
in
@@ -2564,7 +2473,7 @@ let rewrite_vector_concat_assignments defs =
begin
try check_exp env e_aux unit_typ with
| Type_error (l, err) ->
- raise (Reporting_basic.err_typ l (Type_error.string_of_type_error err))
+ raise (Reporting.err_typ l (Type_error.string_of_type_error err))
end
else E_aux (e_aux, annot)
| _ -> E_aux (e_aux, annot)
@@ -2585,12 +2494,15 @@ let rewrite_tuple_assignments defs =
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_tup (List.map (fun id -> mk_pat (P_id id)) ids))) (strip_exp exp) 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
begin
try check_exp env let_exp unit_typ with
| Type_error (l, err) ->
- raise (Reporting_basic.err_typ l (Type_error.string_of_type_error err))
+ raise (Reporting.err_typ l (Type_error.string_of_type_error err))
end
| _ -> E_aux (e_aux, annot)
in
@@ -2635,7 +2547,7 @@ let rewrite_defs_remove_blocks =
let e_aux = function
| (E_block es,(l,_)) -> f l es
| (e,annot) -> E_aux (e,annot) in
-
+
let alg = { id_exp_alg with e_aux = e_aux } in
rewrite_defs_base
@@ -2666,7 +2578,7 @@ let letbind (v : 'a exp) (body : 'a exp -> 'a exp) : 'a exp =
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))
| None ->
- raise (Reporting_basic.err_unreachable l __POS__ "no type information")
+ 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 =
@@ -2681,7 +2593,7 @@ let rewrite_defs_letbind_effects =
and value_optdefault (Def_val_aux (o,_)) = match o with
| Def_val_empty -> true
| Def_val_dec e -> value e
- and value_fexps (FES_aux (FES_Fexps (fexps,_),_)) =
+ and value_fexps fexps =
List.fold_left (fun b (FE_aux (FE_Fexp (_,e),_)) -> b && value e) true fexps in
@@ -2712,11 +2624,6 @@ let rewrite_defs_letbind_effects =
and n_pexpL (newreturn : bool) (pexps : 'a pexp list) (k : 'a pexp list -> 'a exp) : 'a exp =
mapCont (n_pexp newreturn) pexps k
- and n_fexps (fexps : 'a fexps) (k : 'a fexps -> 'a exp) : 'a exp =
- let (FES_aux (FES_Fexps (fexps_aux,b),annot)) = fexps in
- n_fexpL fexps_aux (fun fexps_aux ->
- k (fix_eff_fexps (FES_aux (FES_Fexps (fexps_aux,b),annot))))
-
and n_opt_default (opt_default : 'a opt_default) (k : 'a opt_default -> 'a exp) : 'a exp =
let (Def_val_aux (opt_default,annot)) = opt_default in
match opt_default with
@@ -2865,11 +2772,11 @@ let rewrite_defs_letbind_effects =
n_exp_name exp2 (fun exp2 ->
k (rewrap (E_cons (exp1,exp2)))))
| E_record fexps ->
- n_fexps fexps (fun fexps ->
+ n_fexpL fexps (fun fexps ->
k (rewrap (E_record fexps)))
| E_record_update (exp1,fexps) ->
n_exp_name exp1 (fun exp1 ->
- n_fexps fexps (fun fexps ->
+ n_fexpL fexps (fun fexps ->
k (rewrap (E_record_update (exp1,fexps)))))
| E_field (exp1,id) ->
n_exp_name exp1 (fun exp1 ->
@@ -2962,7 +2869,7 @@ let rewrite_defs_internal_lets =
| LEXP_id id -> P_aux (P_id id, annot)
| LEXP_cast (typ, id) -> add_p_typ typ (P_aux (P_id id, annot))
| LEXP_tup lexps -> P_aux (P_tup (List.map pat_of_local_lexp lexps), annot)
- | _ -> raise (Reporting_basic.err_unreachable l __POS__ "unexpected local lexp") in
+ | _ -> raise (Reporting.err_unreachable l __POS__ "unexpected local lexp") in
let e_let (lb,body) =
match lb with
@@ -3026,13 +2933,13 @@ let rewrite_pexp_with_guards rewrite_pat (Pat_aux (pexp_aux, (annot: tannot anno
| [] -> pexp
| gs ->
let unchecked_pexp = mk_pexp (Pat_when (strip_pat pat, List.map strip_exp gs |> fold_guards, strip_exp exp)) in
- check_case (pat_env_of pat) (pat_typ_of pat) unchecked_pexp (typ_of exp)
+ check_case (env_of_pat pat) (typ_of_pat pat) unchecked_pexp (typ_of exp)
end
| Pat_when (pat, guard, exp) ->
begin
let pat = fold_pat { id_pat_alg with p_aux = rewrite_pat guards } pat in
let unchecked_pexp = mk_pexp (Pat_when (strip_pat pat, List.map strip_exp !guards |> fold_guards, strip_exp exp)) in
- check_case (pat_env_of pat) (pat_typ_of pat) unchecked_pexp (typ_of exp)
+ check_case (env_of_pat pat) (typ_of_pat pat) unchecked_pexp (typ_of exp)
end
@@ -3071,7 +2978,7 @@ let rec bindings_of_pat (P_aux (p_aux, p_annot) as pat) =
| P_record _ -> failwith "record patterns not yet implemented"
(* we assume the type-checker has already checked the two sides have the same bindings *)
| P_or (left, right) -> bindings_of_pat left
- | P_as (p, id) -> [annot_pat (P_id id) unk (pat_env_of p) (pat_typ_of p)]
+ | P_as (p, id) -> [annot_pat (P_id id) unk (env_of_pat p) (typ_of_pat p)]
| P_cons (left, right) -> bindings_of_pat left @ bindings_of_pat right
(* todo: is this right for negated patterns? *)
| P_not p
@@ -3087,11 +2994,11 @@ let rec bindings_of_pat (P_aux (p_aux, p_annot) as pat) =
let rec binding_typs_of_pat (P_aux (p_aux, p_annot) as pat) =
match p_aux with
| P_lit _ | P_wild -> []
- | P_id id -> [pat_typ_of pat]
+ | P_id id -> [typ_of_pat pat]
| P_record _ -> failwith "record patterns not yet implemented"
(* we assume the type-checker has already checked the two sides have the same bindings *)
| P_or (left, right) -> binding_typs_of_pat left
- | P_as (p, id) -> [pat_typ_of p]
+ | P_as (p, id) -> [typ_of_pat p]
| P_cons (left, right) -> binding_typs_of_pat left @ binding_typs_of_pat right
(* todo: is this right for negated patterns? *)
| P_not p
@@ -3107,7 +3014,7 @@ let rec binding_typs_of_pat (P_aux (p_aux, p_annot) as pat) =
let construct_toplevel_string_append_call env f_id bindings binding_typs guard expr =
(* s# if match f#(s#) { Some (bindings) => guard, _ => false) } => let Some(bindings) = f#(s#) in expr *)
let s_id = fresh_stringappend_id () in
- let option_typ = app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ (match binding_typs with
+ let option_typ = app_typ (mk_id "option") [A_aux (A_typ (match binding_typs with
| [] -> unit_typ
| [typ] -> typ
| typs -> tuple_typ typs
@@ -3139,13 +3046,13 @@ let construct_toplevel_string_append_func env f_id pat =
else
bindings
in
- let option_typ = app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ (match binding_typs with
+ let option_typ = app_typ (mk_id "option") [A_aux (A_typ (match binding_typs with
| [] -> unit_typ
| [typ] -> typ
| typs -> tuple_typ typs
), unk)]
in
- let fun_typ = (mk_typ (Typ_fn (string_typ, option_typ, no_effect))) in
+ let fun_typ = (mk_typ (Typ_fn ([string_typ], option_typ, no_effect))) in
let new_val_spec = VS_aux (VS_val_spec (mk_typschm (TypQ_aux (TypQ_no_forall, unk)) fun_typ, f_id, (fun _ -> None), false), unkt) in
let new_val_spec, env = Type_check.check_val_spec env new_val_spec in
let non_rec = (Rec_aux (Rec_nonrec, Parse_ast.Unknown)) in
@@ -3199,7 +3106,7 @@ let construct_toplevel_string_append_func env f_id pat =
in
let mapping_inner_typ =
match Env.get_val_spec (mk_id mapping_prefix_func) env with
- | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [Typ_arg_aux (Typ_arg_typ typ, _)]), _), _), _)) -> typ
+ | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [A_aux (A_typ typ, _)]), _), _), _)) -> typ
| _ -> typ_error Parse_ast.Unknown "mapping prefix func without correct function type?"
in
@@ -3216,11 +3123,11 @@ let construct_toplevel_string_append_func env f_id pat =
[annot_exp (E_id s_id) unk env string_typ]))
unk env mapping_inner_typ in
(* construct some pattern -- Some (n#, len#) *)
- let opt_typ = app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ mapping_inner_typ, unk)] in
+ let opt_typ = app_typ (mk_id "option") [A_aux (A_typ mapping_inner_typ, unk)] in
let tup_arg_pat = match arg_pats with
| [] -> assert false
| [arg_pat] -> arg_pat
- | arg_pats -> annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map pat_typ_of arg_pats))
+ | arg_pats -> annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map typ_of_pat arg_pats))
in
let some_pat = annot_pat (P_app (mk_id "Some",
@@ -3375,7 +3282,7 @@ let rec rewrite_defs_pat_string_append =
in
let mapping_inner_typ =
match Env.get_val_spec (mk_id mapping_prefix_func) env with
- | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [Typ_arg_aux (Typ_arg_typ typ, _)]), _), _), _)) -> typ
+ | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [A_aux (A_typ typ, _)]), _), _), _)) -> typ
| _ -> typ_error Parse_ast.Unknown "mapping prefix func without correct function type?"
in
@@ -3392,11 +3299,11 @@ let rec rewrite_defs_pat_string_append =
[annot_exp (E_id s_id) unk env string_typ]))
unk env mapping_inner_typ in
(* construct some pattern -- Some (n#, len#) *)
- let opt_typ = app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ mapping_inner_typ, unk)] in
+ let opt_typ = app_typ (mk_id "option") [A_aux (A_typ mapping_inner_typ, unk)] in
let tup_arg_pat = match arg_pats with
| [] -> assert false
| [arg_pat] -> arg_pat
- | arg_pats -> annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map pat_typ_of arg_pats))
+ | arg_pats -> annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map typ_of_pat arg_pats))
in
let some_pat = annot_pat (P_app (mk_id "Some",
@@ -3444,13 +3351,13 @@ let rec rewrite_defs_pat_string_append =
| [] -> assert false
| [arg_pat] -> annot_letbind
(P_tup [arg_pat; annot_pat (P_id len_id) unk env nat_typ], new_binding)
- unk env (tuple_typ [pat_typ_of arg_pat; nat_typ])
+ unk env (tuple_typ [typ_of_pat arg_pat; nat_typ])
| arg_pats -> annot_letbind
(P_tup
- [annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map pat_typ_of arg_pats));
+ [annot_pat (P_tup arg_pats) unk env (tuple_typ (List.map typ_of_pat arg_pats));
annot_pat (P_id len_id) unk env nat_typ],
new_binding)
- unk env (tuple_typ [tuple_typ (List.map pat_typ_of arg_pats); nat_typ])
+ unk env (tuple_typ [tuple_typ (List.map typ_of_pat arg_pats); nat_typ])
in
let new_let = annot_exp (E_let (new_letbind, new_match)) unk env (typ_of expr) in
@@ -3556,7 +3463,7 @@ let rewrite_defs_mapping_patterns =
expr_ref := e;
p
in
- let env = pat_env_of pat in
+ let env = env_of_pat pat in
match pat with
(*
mapping(args) if g => expr ----> s# if mapping_matches(s#)
@@ -3705,8 +3612,6 @@ let rewrite_defs_pat_lits rewrite_lit =
let counter = ref 0 in
let rewrite_pat = function
- (* HACK: ignore strings for now *)
- | P_lit (L_aux (L_string _, _)) as p_aux, p_annot -> P_aux (p_aux, p_annot)
(* Matching on unit is always the same as matching on wildcard *)
| P_lit (L_aux (L_unit, _) as lit), p_annot when rewrite_lit lit ->
P_aux (P_wild, p_annot)
@@ -3765,10 +3670,10 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let tuple_pat = function
| [] -> annot_pat P_wild l env unit_typ
| [pat] ->
- let typ = pat_typ_of pat in
+ let typ = typ_of_pat pat in
add_p_typ typ pat
| pats ->
- let typ = tuple_typ (List.map pat_typ_of pats) in
+ let typ = tuple_typ (List.map typ_of_pat pats) in
add_p_typ typ (annot_pat (P_tup pats) l env typ) in
let rec add_vars overwrite ((E_aux (expaux,annot)) as exp) vars =
@@ -3828,9 +3733,9 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
in
let exp4 = rewrite_var_updates (add_vars overwrite exp4 vars) in
let ord_exp, kids, constr, lower, upper, lower_exp, upper_exp =
- match destruct_numeric env (typ_of exp1), destruct_numeric env (typ_of exp2) with
+ match destruct_numeric (Env.expand_synonyms env (typ_of exp1)), destruct_numeric (Env.expand_synonyms env (typ_of exp2)) with
| None, _ | _, None ->
- raise (Reporting_basic.err_unreachable el __POS__ "Could not determine loop bounds")
+ raise (Reporting.err_unreachable el __POS__ "Could not determine loop bounds")
| Some (kids1, constr1, n1), Some (kids2, constr2, n2) ->
let kids = kids1 @ kids2 in
let constr = nc_and constr1 constr2 in
@@ -3844,7 +3749,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
(* Bind the loop variable in the body, annotated with constraints *)
let lvar_kid = mk_kid ("loop_" ^ string_of_id id) in
let lvar_nc = nc_and constr (nc_and (nc_lteq lower (nvar lvar_kid)) (nc_lteq (nvar lvar_kid) upper)) in
- let lvar_typ = mk_typ (Typ_exist (lvar_kid :: kids, lvar_nc, atom_typ (nvar lvar_kid))) in
+ let lvar_typ = mk_typ (Typ_exist (List.map (mk_kopt K_int) (lvar_kid :: kids), lvar_nc, atom_typ (nvar lvar_kid))) in
let lvar_pat = unaux_pat (add_p_typ lvar_typ (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
@@ -3936,7 +3841,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let pannot = (l, mk_tannot (env_of exp) (typ_of exp) (effect_of exp)) in
Pat_aux (Pat_exp (pat, exp), pannot)
| Pat_when _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"Guarded patterns should have been rewritten already") in
let ps = List.map rewrite_pexp ps in
let expaux = if is_case then E_case (e1, ps) else E_try (e1, ps) in
@@ -3950,7 +3855,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
| Local (_, typ) ->
add_p_typ typ (annot_pat (P_id id) pl env typ)
| _ ->
- raise (Reporting_basic.err_unreachable pl __POS__
+ raise (Reporting.err_unreachable pl __POS__
("Failed to look up type of variable " ^ string_of_id id)) in
if effectful exp then
Same_vars (E_aux (E_assign (lexp,vexp),annot))
@@ -3996,7 +3901,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
| LEXP_aux (LEXP_cast (typ, id), _) ->
unaux_pat (add_p_typ typ (annot_pat (P_id id) l env (typ_of v))), typ
| _ ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"E_var with a lexp that is not a variable") in
let lb = fix_eff_lb (annot_letbind (paux, v) l env typ) in
let exp = fix_eff_exp (annot_exp (E_let (lb, body)) l env (typ_of body)) in
@@ -4025,14 +3930,14 @@ let remove_reference_types exp =
let rec rewrite_t (Typ_aux (t_aux,a)) = (Typ_aux (rewrite_t_aux t_aux,a))
and rewrite_t_aux t_aux = match t_aux with
- | Typ_app (Id_aux (Id "reg",_), [Typ_arg_aux (Typ_arg_typ (Typ_aux (t_aux2, _)), _)]) ->
+ | Typ_app (Id_aux (Id "reg",_), [A_aux (A_typ (Typ_aux (t_aux2, _)), _)]) ->
rewrite_t_aux t_aux2
| Typ_app (name,t_args) -> Typ_app (name,List.map rewrite_t_arg t_args)
- | Typ_fn (t1,t2,eff) -> Typ_fn (rewrite_t t1,rewrite_t t2,eff)
+ | Typ_fn (arg_typs, ret_typ, eff) -> Typ_fn (List.map rewrite_t arg_typs, rewrite_t ret_typ, eff)
| Typ_tup ts -> Typ_tup (List.map rewrite_t ts)
| _ -> t_aux
and rewrite_t_arg t_arg = match t_arg with
- | Typ_arg_aux (Typ_arg_typ t, a) -> Typ_arg_aux (Typ_arg_typ (rewrite_t t), a)
+ | A_aux (A_typ t, a) -> A_aux (A_typ (rewrite_t t), a)
| _ -> t_arg in
let rec rewrite_annot (l, tannot) =
@@ -4077,6 +3982,56 @@ let rewrite_defs_remove_superfluous_letbinds =
; rewrite_defs = rewrite_defs_base
}
+(* FIXME: We shouldn't allow nested not-patterns *)
+let rewrite_defs_not_pats =
+ let rewrite_pexp (pexp_aux, annot) =
+ let rewrite_pexp' pat exp orig_guard =
+ let guards = ref [] in
+ let not_counter = ref 0 in
+ let rewrite_not_pat (pat_aux, annot) =
+ match pat_aux with
+ | P_not pat ->
+ incr not_counter;
+ let np_id = mk_id ("np#" ^ string_of_int !not_counter) in
+ let guard =
+ mk_exp (E_case (mk_exp (E_id np_id),
+ [mk_pexp (Pat_exp (strip_pat pat, mk_lit_exp L_false));
+ mk_pexp (Pat_exp (mk_pat P_wild, mk_lit_exp L_true))]))
+ in
+ guards := (np_id, typ_of_annot annot, guard) :: !guards;
+ P_aux (P_id np_id, annot)
+
+ | _ -> P_aux (pat_aux, annot)
+ in
+ let pat = fold_pat { id_pat_alg with p_aux = rewrite_not_pat } pat in
+ begin match !guards with
+ | [] ->
+ Pat_aux (pexp_aux, annot)
+ | guards ->
+ let guard_exp =
+ match orig_guard, guards with
+ | Some guard, _ ->
+ List.fold_left (fun exp1 (_, _, exp2) -> mk_exp (E_app_infix (exp1, mk_id "&", exp2))) guard guards
+ | None, (_, _, guard) :: guards ->
+ List.fold_left (fun exp1 (_, _, exp2) -> mk_exp (E_app_infix (exp1, mk_id "&", exp2))) guard guards
+ | _ -> raise (Reporting.err_unreachable (fst annot) __POS__ "Case in not-pattern re-writing should be unreachable")
+ in
+ (* We need to construct an environment to check the match guard in *)
+ let env = env_of_pat pat in
+ let env = List.fold_left (fun env (np_id, np_typ, _) -> Env.add_local np_id (Immutable, np_typ) env) env guards in
+ let guard_exp = Type_check.check_exp env guard_exp bool_typ in
+ Pat_aux (Pat_when (pat, guard_exp, exp), annot)
+ end
+ in
+ match pexp_aux with
+ | Pat_exp (pat, exp) ->
+ rewrite_pexp' pat exp None
+ | Pat_when (pat, guard, exp) ->
+ rewrite_pexp' pat exp (Some (strip_exp guard))
+ in
+ let rw_exp = { id_exp_alg with pat_aux = rewrite_pexp } in
+ rewrite_defs_base { rewriters_base with rewrite_exp = (fun _ -> fold_exp rw_exp) }
+
let rewrite_defs_remove_superfluous_returns =
let add_opt_cast typopt1 typopt2 annot exp =
@@ -4198,7 +4153,7 @@ and fexps_of_mfpats mfpats flag annot =
let fexp_of_mfpat (MFP_aux (MFP_mpat (id, mpat), annot)) =
FE_aux (FE_Fexp (id, exp_of_mpat mpat), annot)
in
- FES_aux (FES_Fexps (List.map fexp_of_mfpat mfpats, flag), annot)
+ List.map fexp_of_mfpat mfpats
and pat_of_mpat (MP_aux (mpat, annot)) =
match mpat with
@@ -4327,7 +4282,8 @@ let rewrite_defs_realise_mappings (Defs defs) =
let non_rec = (Rec_aux (Rec_nonrec, Parse_ast.Unknown)) in
let effect_pure = (Effect_opt_aux (Effect_opt_pure, Parse_ast.Unknown)) in
- let env = match mapcls with
+ (* We need to make sure we get the environment for the last mapping clause *)
+ let env = match List.rev mapcls with
| MCL_aux (_, mapcl_annot) :: _ -> env_of_annot mapcl_annot
| _ -> Type_check.typ_error l "mapping with no clauses?"
in
@@ -4336,10 +4292,10 @@ let rewrite_defs_realise_mappings (Defs defs) =
| Typ_aux (Typ_bidir (typ1, typ2), l) -> typ1, typ2, l
| _ -> Type_check.typ_error l "non-bidir type of mapping?"
in
- let forwards_typ = Typ_aux (Typ_fn (typ1, typ2, no_effect), l) in
- let forwards_matches_typ = Typ_aux (Typ_fn (typ1, bool_typ, no_effect), l) in
- let backwards_typ = Typ_aux (Typ_fn (typ2, typ1, no_effect), l) in
- let backwards_matches_typ = Typ_aux (Typ_fn (typ2, bool_typ, no_effect), l) in
+ let forwards_typ = Typ_aux (Typ_fn ([typ1], typ2, no_effect), l) in
+ let forwards_matches_typ = Typ_aux (Typ_fn ([typ1], bool_typ, no_effect), l) in
+ let backwards_typ = Typ_aux (Typ_fn ([typ2], typ1, no_effect), l) in
+ let backwards_matches_typ = Typ_aux (Typ_fn ([typ2], bool_typ, no_effect), l) in
let forwards_spec = VS_aux (VS_val_spec (mk_typschm typq forwards_typ, forwards_id, (fun _ -> None), false), (Parse_ast.Unknown,())) in
let backwards_spec = VS_aux (VS_val_spec (mk_typschm typq backwards_typ, backwards_id, (fun _ -> None), false), (Parse_ast.Unknown,())) in
@@ -4377,7 +4333,7 @@ let rewrite_defs_realise_mappings (Defs defs) =
let prefix_wildcard = mk_pexp (Pat_exp (mk_pat P_wild, mk_exp (E_app (mk_id "None", [mk_exp (E_lit (mk_lit L_unit))])))) in
let string_defs =
begin if subtype_check env typ1 string_typ && subtype_check env string_typ typ1 then
- let forwards_prefix_typ = Typ_aux (Typ_fn (typ1, app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ (tuple_typ [typ2; nat_typ]), Parse_ast.Unknown)], no_effect), Parse_ast.Unknown) in
+ let forwards_prefix_typ = Typ_aux (Typ_fn ([typ1], app_typ (mk_id "option") [A_aux (A_typ (tuple_typ [typ2; nat_typ]), Parse_ast.Unknown)], no_effect), Parse_ast.Unknown) in
let forwards_prefix_spec = VS_aux (VS_val_spec (mk_typschm typq forwards_prefix_typ, prefix_id, (fun _ -> None), false), (Parse_ast.Unknown,())) in
let forwards_prefix_spec, env = Type_check.check_val_spec env forwards_prefix_spec in
let forwards_prefix_match = mk_exp (E_case (arg_exp, ((List.map (fun mapcl -> strip_mapcl mapcl |> realise_prefix_mapcl true prefix_id) mapcls) |> List.flatten) @ [prefix_wildcard])) in
@@ -4387,7 +4343,7 @@ let rewrite_defs_realise_mappings (Defs defs) =
forwards_prefix_spec @ forwards_prefix_fun
else
if subtype_check env typ2 string_typ && subtype_check env string_typ typ2 then
- let backwards_prefix_typ = Typ_aux (Typ_fn (typ2, app_typ (mk_id "option") [Typ_arg_aux (Typ_arg_typ (tuple_typ [typ1; nat_typ]), Parse_ast.Unknown)], no_effect), Parse_ast.Unknown) in
+ let backwards_prefix_typ = Typ_aux (Typ_fn ([typ2], app_typ (mk_id "option") [A_aux (A_typ (tuple_typ [typ1; nat_typ]), Parse_ast.Unknown)], no_effect), Parse_ast.Unknown) in
let backwards_prefix_spec = VS_aux (VS_val_spec (mk_typschm typq backwards_prefix_typ, prefix_id, (fun _ -> None), false), (Parse_ast.Unknown,())) in
let backwards_prefix_spec, env = Type_check.check_val_spec env backwards_prefix_spec in
let backwards_prefix_match = mk_exp (E_case (arg_exp, ((List.map (fun mapcl -> strip_mapcl mapcl |> realise_prefix_mapcl false prefix_id) mapcls) |> List.flatten) @ [prefix_wildcard])) in
@@ -4512,9 +4468,7 @@ let make_cstr_mappings env ids m =
(fun id ->
let _,ty = Env.get_val_spec id env in
let args = match ty with
- | Typ_aux (Typ_fn (Typ_aux (Typ_tup [Typ_aux (Typ_tup tys,_)],_),_,_),_)
- | Typ_aux (Typ_fn (Typ_aux (Typ_tup tys,_),_,_),_)
- -> List.map (fun _ -> RP_any) tys
+ | Typ_aux (Typ_fn (tys,_,_),_) -> List.map (fun _ -> RP_any) tys
| _ -> [RP_any]
in RP_app (id,args)) ids in
let rec aux ids acc l =
@@ -4551,7 +4505,7 @@ let rec remove_clause_from_pattern ctx (P_aux (rm_pat,ann)) res_pat =
in aux [] res_pats res_pats'
in
let inconsistent () =
- raise (Reporting_basic.err_unreachable (fst ann) __POS__
+ raise (Reporting.err_unreachable (fst ann) __POS__
("Inconsistency during exhaustiveness analysis with " ^
string_of_rp res_pat))
in
@@ -4593,7 +4547,16 @@ let rec remove_clause_from_pattern ctx (P_aux (rm_pat,ann)) res_pat =
(match res_pat with
| RP_app (id',residual_args) ->
if Id.compare id id' == 0 then
- let res_pats' = subpats args residual_args in
+ let res_pats' =
+ (* Constructors that were specified without a return type might get
+ an extra tuple in their type; expand that here if necessary.
+ TODO: this should go away if we enforce proper arities. *)
+ match args, residual_args with
+ | [], [RP_any]
+ | _::_::_, [RP_any]
+ -> subpats args (List.map (fun _ -> RP_any) args)
+ | _,_ ->
+ subpats args residual_args in
List.map (fun rps -> RP_app (id,rps)) res_pats'
else [res_pat]
| RP_any ->
@@ -4626,12 +4589,12 @@ let rec remove_clause_from_pattern ctx (P_aux (rm_pat,ann)) res_pat =
rp' @ List.map (function [rp1;rp2] -> RP_cons (rp1,rp2) | _ -> assert false) res_pats
end
| P_record _ ->
- raise (Reporting_basic.err_unreachable (fst ann) __POS__
+ raise (Reporting.err_unreachable (fst ann) __POS__
"Record pattern not supported")
| P_vector _
| P_vector_concat _
| P_string_append _ ->
- raise (Reporting_basic.err_unreachable (fst ann) __POS__
+ raise (Reporting.err_unreachable (fst ann) __POS__
"Found pattern that should have been rewritten away in earlier stage")
(*in let _ = printprefix := String.sub (!printprefix) 0 (String.length !printprefix - 2)
@@ -4647,7 +4610,7 @@ let process_pexp env =
| Pat_aux (Pat_exp (p,_),_) ->
List.concat (List.map (remove_clause_from_pattern ctx p) rps)
| Pat_aux (Pat_when _,(l,_)) ->
- raise (Reporting_basic.err_unreachable l __POS__
+ raise (Reporting.err_unreachable l __POS__
"Guarded pattern should have been rewritten away")
(* We do some minimal redundancy checking to remove bogus wildcard patterns here *)
@@ -4655,7 +4618,7 @@ let check_cases process is_wild loc_of cases =
let rec aux rps acc = function
| [] -> acc, rps
| [p] when is_wild p && match rps with [] -> true | _ -> false ->
- let () = Reporting_basic.print_err false false
+ let () = Reporting.print_err false false
(loc_of p) "Match checking" "Redundant wildcard clause" in
acc, []
| h::t -> aux (process rps h) (h::acc) t
@@ -4695,7 +4658,7 @@ let rewrite_case (e,ann) =
let _ =
if !opt_coq_warn_nonexhaustive
- then Reporting_basic.print_err false false
+ then Reporting.print_err false false
(fst ann) "Non-exhaustive matching" ("Example: " ^ string_of_rp example) in
let l = Parse_ast.Generated Parse_ast.Unknown in
@@ -4715,7 +4678,7 @@ let rewrite_case (e,ann) =
| (example::_) ->
let _ =
if !opt_coq_warn_nonexhaustive
- then Reporting_basic.print_err false false
+ then Reporting.print_err false false
(fst ann) "Non-exhaustive let" ("Example: " ^ string_of_rp example) in
let l = Parse_ast.Generated Parse_ast.Unknown in
let p = P_aux (P_wild, (l, empty_tannot)) in
@@ -4731,7 +4694,7 @@ let rewrite_fun rewriters (FD_aux (FD_function (r,t,e,fcls),f_ann)) =
let id,fcl_ann =
match fcls with
| FCL_aux (FCL_Funcl (id,_),ann) :: _ -> id,ann
- | [] -> raise (Reporting_basic.err_unreachable (fst f_ann) __POS__
+ | [] -> raise (Reporting.err_unreachable (fst f_ann) __POS__
"Empty function")
in
let env = env_of_annot fcl_ann in
@@ -4745,7 +4708,7 @@ let rewrite_fun rewriters (FD_aux (FD_function (r,t,e,fcls),f_ann)) =
| (example::_) ->
let _ =
if !opt_coq_warn_nonexhaustive
- then Reporting_basic.print_err false false
+ then Reporting.print_err false false
(fst f_ann) "Non-exhaustive matching" ("Example: " ^ string_of_rp example) in
let l = Parse_ast.Generated Parse_ast.Unknown in
@@ -4790,7 +4753,7 @@ let minimise_recursive_functions (Defs defs) =
let rewrite_function (FD_aux (FD_function (recopt,topt,effopt,funcls),ann) as fd) =
match recopt with
| Rec_aux (Rec_nonrec, _) -> fd
- | Rec_aux (Rec_rec, l) ->
+ | Rec_aux ((Rec_rec | Rec_measure _), l) ->
if List.exists funcl_is_rec funcls
then fd
else FD_aux (FD_function (Rec_aux (Rec_nonrec, Generated l),topt,effopt,funcls),ann)
@@ -4800,7 +4763,150 @@ let minimise_recursive_functions (Defs defs) =
| d -> d
in Defs (List.map rewrite_def defs)
+(* Make recursive functions with a measure use the measure as an
+ explicit recursion limit, enforced by an assertion. *)
+let rewrite_explicit_measure (Defs defs) =
+ let scan_function measures = function
+ | FD_aux (FD_function (Rec_aux (Rec_measure (mpat,mexp),rl),topt,effopt,
+ FCL_aux (FCL_Funcl (id,_),_)::_),ann) ->
+ Bindings.add id (mpat,mexp) measures
+ | _ -> measures
+ in
+ let scan_def measures = function
+ | DEF_fundef fd -> scan_function measures fd
+ | _ -> measures
+ in
+ let measures = List.fold_left scan_def Bindings.empty defs in
+ let add_escape eff =
+ union_effects eff (mk_effect [BE_escape])
+ in
+ (* NB: the Coq backend relies on recognising the #rec# prefix *)
+ let rec_id = function
+ | Id_aux (Id id,l)
+ | Id_aux (DeIid id,l) -> Id_aux (Id ("#rec#" ^ id),Generated l)
+ in
+ let limit = mk_id "#reclimit" in
+ (* Add helper function with extra argument to spec *)
+ let rewrite_spec (VS_aux (VS_val_spec (typsch,id,extern,flag),ann) as vs) =
+ match Bindings.find id measures with
+ | _ -> begin
+ match typsch with
+ | TypSchm_aux (TypSchm_ts (tq,
+ Typ_aux (Typ_fn (args,res,eff),typl)),tsl) ->
+ [VS_aux (VS_val_spec (
+ TypSchm_aux (TypSchm_ts (tq,
+ Typ_aux (Typ_fn (args@[int_typ],res,add_escape eff),typl)),tsl)
+ ,rec_id id,extern,flag),ann);
+ VS_aux (VS_val_spec (
+ TypSchm_aux (TypSchm_ts (tq,
+ Typ_aux (Typ_fn (args,res,add_escape eff),typl)),tsl)
+ ,id,extern,flag),ann)]
+ | _ -> [vs] (* TODO warn *)
+ end
+ | exception Not_found -> [vs]
+ in
+ (* Add extra argument and assertion to each funcl, and rewrite recursive calls *)
+ let rewrite_funcl (FCL_aux (FCL_Funcl (id,pexp),ann) as fcl) =
+ let loc = Parse_ast.Generated (fst ann) in
+ let P_aux (pat,pann),guard,body,ann = destruct_pexp pexp in
+ let extra_pat = P_aux (P_id limit,(loc,empty_tannot)) in
+ let pat = match pat with
+ | P_tup pats -> P_tup (pats@[extra_pat])
+ | p -> P_tup [P_aux (p,pann);extra_pat]
+ in
+ let assert_exp =
+ E_aux (E_assert
+ (E_aux (E_app (mk_id "gteq_int",
+ [E_aux (E_id limit,(loc,empty_tannot));
+ E_aux (E_lit (L_aux (L_num Big_int.zero,loc)),(loc,empty_tannot))]),
+ (loc,empty_tannot)),
+ (E_aux (E_lit (L_aux (L_string "recursion limit reached",loc)),(loc,empty_tannot)))),
+ (loc,empty_tannot))
+ in
+ let tick =
+ E_aux (E_app (mk_id "sub_int",
+ [E_aux (E_id limit,(loc,empty_tannot));
+ E_aux (E_lit (L_aux (L_num (Big_int.of_int 1),loc)),(loc,empty_tannot))]),
+ (loc,empty_tannot))
+ in
+ let open Rewriter in
+ let body =
+ fold_exp { id_exp_alg with
+ e_app = (fun (f,args) ->
+ if Id.compare f id == 0
+ then E_app (rec_id id, args@[tick])
+ else E_app (f, args))
+ } body
+ in
+ let body = E_aux (E_block [assert_exp; body],(loc,empty_tannot)) in
+ FCL_aux (FCL_Funcl (rec_id id, construct_pexp (P_aux (pat,pann),guard,body,ann)),ann)
+ in
+ let rewrite_function (FD_aux (FD_function (r,t,e,fcls),ann) as fd) =
+ let loc = Parse_ast.Generated (fst ann) in
+ match fcls with
+ | FCL_aux (FCL_Funcl (id,_),fcl_ann)::_ -> begin
+ match Bindings.find id measures with
+ | (measure_pat, measure_exp) ->
+ let e = match e with
+ | Effect_opt_aux (Effect_opt_pure, _) ->
+ Effect_opt_aux (Effect_opt_effect (mk_effect [BE_escape]), loc)
+ | Effect_opt_aux (Effect_opt_effect eff,_) ->
+ Effect_opt_aux (Effect_opt_effect (add_escape eff), loc)
+ in
+ let arg_typs = match Env.get_val_spec id (env_of_annot fcl_ann) with
+ | _, Typ_aux (Typ_fn (args,_,_),_) -> args
+ | _, _ -> raise (Reporting.err_unreachable (fst ann) __POS__
+ "Function doesn't have function type")
+ in
+ let measure_pats = match arg_typs, measure_pat with
+ | [_], _ -> [measure_pat]
+ | _, P_aux (P_tup ps,_) -> ps
+ | _, _ -> [measure_pat]
+ in
+ let mk_wrap i (P_aux (p,(l,_))) =
+ let id =
+ match p with
+ | P_id id
+ | P_typ (_,(P_aux (P_id id,_))) -> id
+ | P_wild
+ | P_typ (_,(P_aux (P_wild,_))) ->
+ mk_id ("_arg" ^ string_of_int i)
+ | _ -> raise (Reporting.err_todo l "Measure patterns can only be identifiers or wildcards")
+ in
+ P_aux (P_id id,(loc,empty_tannot)),
+ E_aux (E_id id,(loc,empty_tannot))
+ in
+ let wpats,wexps = List.split (Util.list_mapi mk_wrap measure_pats) in
+ let wpat = match wpats with
+ | [wpat] -> wpat
+ | _ -> P_aux (P_tup wpats,(loc,empty_tannot))
+ in
+ let wbody = E_aux (E_app (rec_id id,wexps@[measure_exp]),(loc,empty_tannot)) in
+ let wrapper =
+ FCL_aux (FCL_Funcl (id, Pat_aux (Pat_exp (wpat,wbody),(loc,empty_tannot))),(loc,empty_tannot))
+ in
+ let new_rec =
+ Rec_aux (Rec_measure (P_aux (P_tup (List.map (fun _ -> P_aux (P_wild,(loc,empty_tannot))) measure_pats @ [P_aux (P_id limit,(loc,empty_tannot))]),(loc,empty_tannot)), E_aux (E_id limit, (loc,empty_tannot))), loc)
+ in
+ [FD_aux (FD_function (new_rec,t,e,List.map rewrite_funcl fcls),ann);
+ FD_aux (FD_function (Rec_aux (Rec_nonrec,loc),t,e,[wrapper]),ann)]
+ | exception Not_found -> [fd]
+ end
+ | _ -> [fd]
+ in
+ let rewrite_def = function
+ | DEF_spec vs -> List.map (fun vs -> DEF_spec vs) (rewrite_spec vs)
+ | DEF_fundef fd -> List.map (fun f -> DEF_fundef f) (rewrite_function fd)
+ | d -> [d]
+ in
+ Defs (List.flatten (List.map rewrite_def defs))
+
let recheck_defs defs = fst (Type_error.check initial_env defs)
+let recheck_defs_without_effects defs =
+ let () = opt_no_effects := true in
+ let result,_ = Type_error.check initial_env defs in
+ let () = opt_no_effects := false in
+ result
let remove_mapping_valspecs (Defs defs) =
let allowed_def def =
@@ -4861,6 +4967,7 @@ let rewrite_defs_lem = [
("recheck_defs", if_mono recheck_defs);
("rewrite_undefined", rewrite_undefined_if_gen false);
("rewrite_defs_vector_string_pats_to_bit_list", rewrite_defs_vector_string_pats_to_bit_list);
+ ("remove_not_pats", rewrite_defs_not_pats);
("pat_lits", rewrite_defs_pat_lits rewrite_lit_lem);
("vector_concat_assignments", rewrite_vector_concat_assignments);
("tuple_assignments", rewrite_tuple_assignments);
@@ -4903,6 +5010,7 @@ let rewrite_defs_coq = [
("mapping_builtins", rewrite_defs_mapping_patterns);
("rewrite_undefined", rewrite_undefined_if_gen true);
("rewrite_defs_vector_string_pats_to_bit_list", rewrite_defs_vector_string_pats_to_bit_list);
+ ("remove_not_pats", rewrite_defs_not_pats);
("pat_lits", rewrite_defs_pat_lits rewrite_lit_lem);
("vector_concat_assignments", rewrite_vector_concat_assignments);
("tuple_assignments", rewrite_tuple_assignments);
@@ -4926,8 +5034,9 @@ let rewrite_defs_coq = [
("sizeof", rewrite_sizeof);
("early_return", rewrite_defs_early_return);
("make_cases_exhaustive", MakeExhaustive.rewrite);
+ ("rewrite_explicit_measure", rewrite_explicit_measure);
+ ("recheck_defs_without_effects", recheck_defs_without_effects);
("fix_val_specs", rewrite_fix_val_specs);
- ("recheck_defs", recheck_defs);
("remove_blocks", rewrite_defs_remove_blocks);
("letbind_effects", rewrite_defs_letbind_effects);
("remove_e_assign", rewrite_defs_remove_e_assign);
@@ -4951,6 +5060,7 @@ let rewrite_defs_ocaml = [
("vector_concat_assignments", rewrite_vector_concat_assignments);
("tuple_assignments", rewrite_tuple_assignments);
("simple_assignments", rewrite_simple_assignments);
+ ("remove_not_pats", rewrite_defs_not_pats);
("remove_vector_concat", rewrite_defs_remove_vector_concat);
("remove_bitvector_pats", rewrite_defs_remove_bitvector_pats);
("remove_numeral_pats", rewrite_defs_remove_numeral_pats);
@@ -4972,7 +5082,8 @@ let rewrite_defs_c = [
("mapping_builtins", rewrite_defs_mapping_patterns);
("rewrite_undefined", rewrite_undefined_if_gen false);
("rewrite_defs_vector_string_pats_to_bit_list", rewrite_defs_vector_string_pats_to_bit_list);
- ("pat_lits", rewrite_defs_pat_lits rewrite_no_strings);
+ ("remove_not_pats", rewrite_defs_not_pats);
+ ("pat_lits", rewrite_defs_pat_lits (fun _ -> true));
("vector_concat_assignments", rewrite_vector_concat_assignments);
("tuple_assignments", rewrite_tuple_assignments);
("simple_assignments", rewrite_simple_assignments);
@@ -5010,16 +5121,16 @@ let rewrite_check_annot =
let typ1 = typ_of exp in
let typ2 = Env.expand_synonyms (env_of exp) (typ_of exp) in
(if not (alpha_equivalent (env_of exp) typ1 typ2)
- then raise (Reporting_basic.err_typ Parse_ast.Unknown
+ then raise (Reporting.err_typ Parse_ast.Unknown
("Found synonym in annotation " ^ string_of_typ typ1 ^ " vs " ^ string_of_typ typ2))
else ());
exp
with
- Type_error (l, err) -> raise (Reporting_basic.err_typ l (Type_error.string_of_type_error err))
+ Type_error (l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err))
in
let check_pat pat =
- prerr_endline ("CHECKING PAT: " ^ string_of_pat pat ^ " : " ^ string_of_typ (pat_typ_of pat));
- let _, _ = bind_pat_no_guard (pat_env_of pat) (strip_pat pat) (pat_typ_of pat) in
+ prerr_endline ("CHECKING PAT: " ^ string_of_pat pat ^ " : " ^ string_of_typ (typ_of_pat pat));
+ let _, _ = bind_pat_no_guard (env_of_pat pat) (strip_pat pat) (typ_of_pat pat) in
pat
in