summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/coq/Sail2_prompt.v24
-rw-r--r--src/pretty_print_coq.ml230
2 files changed, 116 insertions, 138 deletions
diff --git a/lib/coq/Sail2_prompt.v b/lib/coq/Sail2_prompt.v
index f5d277e1..741fa921 100644
--- a/lib/coq/Sail2_prompt.v
+++ b/lib/coq/Sail2_prompt.v
@@ -57,16 +57,16 @@ Definition foreach_ZM_down {rv e Vars} from to step vars body `{ArithFact (0 < s
Definition and_boolM {rv E} (l : monad rv bool E) (r : monad rv bool E) : monad rv bool E :=
l >>= (fun l => if l then r else returnm false).
-Definition and_boolMP {rv E} {P Q R:bool->Prop} (x : monad rv {b:bool & P b} E) (y : monad rv {b:bool & Q b} E)
+Definition and_boolMP {rv E} {P Q R:bool->Prop} (x : monad rv {b:bool & ArithFact (P b)} E) (y : monad rv {b:bool & ArithFact (Q b)} E)
`{H:ArithFact (forall l r, P l -> (l = true -> Q r) -> R (andb l r))}
- : monad rv {b:bool & R b} E.
+ : monad rv {b:bool & ArithFact (R b)} E.
refine (
- x >>= fun '(existT _ x p) => (if x return P x -> _ then
+ x >>= fun '(existT _ x (Build_ArithFact _ p)) => (if x return P x -> _ then
fun p => y >>= fun '(existT _ y _) => returnm (existT _ y _)
else fun p => returnm (existT _ false _)) p
).
-* destruct H. change y with (andb true y). auto.
-* destruct H. change false with (andb false false). apply fact.
+* constructor. destruct H. destruct a0. change y with (andb true y). auto.
+* constructor. destruct H. change false with (andb false false). apply fact.
assumption.
congruence.
Defined.
@@ -74,20 +74,20 @@ Defined.
(*val or_boolM : forall 'rv 'e. monad 'rv bool 'e -> monad 'rv bool 'e -> monad 'rv bool 'e*)
Definition or_boolM {rv E} (l : monad rv bool E) (r : monad rv bool E) : monad rv bool E :=
l >>= (fun l => if l then returnm true else r).
-Definition or_boolMP {rv E} {P Q R:bool -> Prop} (l : monad rv {b : bool & P b} E) (r : monad rv {b : bool & Q b} E)
+Definition or_boolMP {rv E} {P Q R:bool -> Prop} (l : monad rv {b : bool & ArithFact (P b)} E) (r : monad rv {b : bool & ArithFact (Q b)} E)
`{ArithFact (forall l r, P l -> (l = false -> Q r) -> R (orb l r))}
- : monad rv {b : bool & R b} E.
+ : monad rv {b : bool & ArithFact (R b)} E.
refine (
- l >>= fun '(existT _ l p) =>
+ l >>= fun '(existT _ l (Build_ArithFact _ p)) =>
(if l return P l -> _ then fun p => returnm (existT _ true _)
else fun p => r >>= fun '(existT _ r _) => returnm (existT _ r _)) p
).
-* destruct H. change true with (orb true true). apply fact. assumption. congruence.
-* destruct H. change r with (orb false r). auto.
+* constructor. destruct H. change true with (orb true true). apply fact. assumption. congruence.
+* constructor. destruct H. destruct a0. change r with (orb false r). auto.
Defined.
-Definition build_trivial_ex {rv E} {T:Type} (x:monad rv T E) : monad rv {x : T & True} E :=
- x >>= fun x => returnm (existT _ x I).
+Definition build_trivial_ex {rv E} {T:Type} (x:monad rv T E) : monad rv {x : T & ArithFact True} E :=
+ x >>= fun x => returnm (existT _ x (Build_ArithFact _ I)).
Definition and_boolBM {rv E P Q} (l : monad rv (Bool P) E) (r : monad rv (Bool Q) E) : monad rv (Bool (P /\ Q)) E.
refine (
diff --git a/src/pretty_print_coq.ml b/src/pretty_print_coq.ml
index 1079d68e..5dfeb7ba 100644
--- a/src/pretty_print_coq.ml
+++ b/src/pretty_print_coq.ml
@@ -467,52 +467,36 @@ let simplify_atom_bool l kopts nc atom_nc =
type ex_kind = ExNone | ExGeneral
-let classify_ex_type (Typ_aux (t,l) as t0) =
+(* Should a Sail type be turned into a dependent pair in Coq?
+ Optionally takes a variable that we're binding (to avoid trivial cases where
+ the type is exactly the boolean we're binding), and whether to turn bools
+ with interesting type-expressions into dependent pairs. *)
+let classify_ex_type ctxt env ?binding ?(rawbools=false) (Typ_aux (t,l) as t0) =
+ let is_binding kid =
+ match binding, KBindings.find_opt kid ctxt.kid_id_renames with
+ | Some id, Some id' when Id.compare id id' == 0 -> true
+ | _ -> false
+ in
+ let simplify_atom_bool l kopts nc atom_nc =
+ match simplify_atom_bool l kopts nc atom_nc with
+ | Bool_boring -> Bool_boring
+ | Bool_complex (_,_,NC_aux (NC_var kid,_)) when is_binding kid -> Bool_boring
+ | Bool_complex (x,y,z) -> Bool_complex (x,y,z)
+ in
match t with
- | Typ_exist (kopts,nc,(Typ_aux (Typ_app (Id_aux (Id "atom_bool",_), [A_aux (A_bool atom_nc,_)]),_) as t1)) -> begin
+ | Typ_exist (kopts,nc,Typ_aux (Typ_app (Id_aux (Id "atom_bool",_), [A_aux (A_bool atom_nc,_)]),_)) -> begin
match simplify_atom_bool l kopts nc atom_nc with
- | Bool_boring -> ExNone, t1
- | Bool_complex _ -> ExGeneral, t1
+ | Bool_boring -> ExNone, [], bool_typ
+ | Bool_complex _ -> ExGeneral, [], bool_typ
end
- | Typ_exist (_,_,t1) -> ExGeneral,t1
- | _ -> ExNone,t0
-
-(* The AST doesn't generally have enough type annotations for the booleans,
- so we attempt to add some (for internal_plet at the moment). This
- function helps by checking that the type variables that appear can be
- printed for Coq, and attempts to replace them if not. *)
-(* TODO: actually check the substitution applies *somewhere* *)
-let clean_typ ctxt env typ =
- let kids = tyvars_of_typ typ in
- let is_equal kid kid' =
- prove __POS__ env (nc_eq (nvar kid) (nvar kid'))
- in
- let check kid subst =
- if KidSet.mem kid ctxt.bound_nvars ||
- KBindings.mem kid ctxt.kid_renames ||
- KBindings.mem kid ctxt.kid_id_renames
- then subst
- else
- match KidSet.find_first_opt (is_equal kid) ctxt.bound_nvars with
- | Some kid' -> KBindings.add kid kid' subst
- | None ->
- match KBindings.find_first_opt (is_equal kid) ctxt.kid_renames with
- | Some (kid',_) -> KBindings.add kid kid' subst
- | None ->
- match KBindings.find_first_opt (is_equal kid) ctxt.kid_id_renames with
- | Some (kid',_) -> KBindings.add kid kid' subst
- | None ->
- raise Not_found
- in
- try
- let subst = KidSet.fold check kids KBindings.empty in
- (* TODO: this is an awful way to do the subsitution! *)
- let typ = KBindings.fold (fun kid kid' typ -> subst_kid typ_subst kid kid' typ) subst typ in
- Some typ
- with Not_found ->
- debug ctxt (lazy ("Failed to clean type " ^ string_of_typ typ ^ " under constraints " ^
- Util.string_of_list ", " string_of_n_constraint (Env.get_constraints env)));
- None
+ | Typ_app (Id_aux (Id "atom_bool",_), [A_aux (A_bool atom_nc,_)]) -> begin
+ match rawbools, simplify_atom_bool l [] nc_true atom_nc with
+ | false, _ -> ExNone, [], bool_typ
+ | _,Bool_boring -> ExNone, [], bool_typ
+ | _,Bool_complex _ -> ExGeneral, [], bool_typ
+ end
+ | Typ_exist (kopts,_,t1) -> ExGeneral,kopts,t1
+ | _ -> ExNone,[],t0
(* When making changes here, check whether they affect coq_nvars_of_typ *)
let rec doc_typ_fns ctx =
@@ -557,14 +541,17 @@ let rec doc_typ_fns ctx =
(string "Z")
| Typ_app(Id_aux (Id "atom", _), [A_aux(A_nexp n,_)]) ->
(string "Z")
- | Typ_app(Id_aux (Id "atom_bool", _), [_]) -> string "bool"
- | Typ_app (Id_aux (Id "atom#bool",_), [A_aux (A_bool atom_nc,_)]) ->
- let var = mk_kid "_bool" in (* TODO collision avoid *)
- let nc = nice_iff (nc_var var) atom_nc in
- braces (separate space
- [doc_var ctx var; colon; string "bool";
- ampersand;
- doc_arithfact ctx nc])
+ | Typ_app(Id_aux (Id "atom_bool", _), [A_aux (A_bool atom_nc,_)]) ->
+ begin match simplify_atom_bool l [] nc_true atom_nc with
+ | Bool_boring -> string "bool"
+ | Bool_complex (_,_,atom_nc) -> (* simplify won't introduce new kopts *)
+ let var = mk_kid "_bool" in (* TODO collision avoid *)
+ let nc = nice_iff (nc_var var) atom_nc in
+ braces (separate space
+ [doc_var ctx var; colon; string "bool";
+ ampersand;
+ doc_arithfact ctx nc])
+ end
| Typ_app(id,args) ->
let tpp = (doc_id_type id) ^^ space ^^ (separate_map space doc_typ_arg args) in
if atyp_needed then parens tpp else tpp
@@ -933,11 +920,11 @@ let is_ctor env id = match Env.lookup_id id env with
| Enum _ -> true
| _ -> false
-let is_auto_decomposed_exist env typ =
+let is_auto_decomposed_exist ctxt env ?(rawbools=false) typ =
let typ = expand_range_type typ in
- match classify_ex_type (Env.expand_synonyms env typ) with
- | ExGeneral, typ' -> Some typ'
- | ExNone, _ -> None
+ match classify_ex_type ctxt env ~rawbools (Env.expand_synonyms env typ) with
+ | ExGeneral, kopts, typ' -> Some (kopts, typ')
+ | ExNone, _, _ -> None
(*Note: vector concatenation, literal vectors, indexed vectors, and record should
be removed prior to pp. The latter two have never yet been seen
@@ -945,10 +932,11 @@ let is_auto_decomposed_exist env typ =
let rec doc_pat ctxt apat_needed exists_as_pairs (P_aux (p,(l,annot)) as pat, typ) =
let env = env_of_annot (l,annot) in
let typ = Env.expand_synonyms env typ in
- match exists_as_pairs, is_auto_decomposed_exist env typ with
- | true, Some typ' ->
-(*prerr_endline ("decomposing for pattern " ^ string_of_pat pat ^ " at type " ^ string_of_typ typ ^ " with internal type " ^ string_of_typ typ');*)
- let pat_pp = doc_pat ctxt true true (pat, typ') in
+ match exists_as_pairs, is_auto_decomposed_exist ctxt env typ with
+ | true, Some (kopts,typ') ->
+ debug ctxt (lazy ("decomposing for pattern " ^ string_of_pat pat ^ " at type " ^ string_of_typ typ ^ " with internal type " ^ string_of_typ typ'));
+ let ctxt' = { ctxt with bound_nvars = List.fold_left (fun s kopt -> KidSet.add (kopt_kid kopt) s) ctxt.bound_nvars kopts } in
+ let pat_pp = doc_pat ctxt' true true (pat, typ') in
let pat_pp = separate space [string "existT"; underscore; pat_pp; underscore] in
if apat_needed then parens pat_pp else pat_pp
| _ ->
@@ -1134,10 +1122,8 @@ let replace_atom_return_type ret_typ =
| Typ_aux (Typ_app (Id_aux (Id "atom",_), [A_aux (A_nexp nexp,_)]),l) ->
let kid = mk_kid "_retval" in (* TODO: collision avoidance *)
Some "build_ex", Typ_aux (Typ_exist ([mk_kopt K_int kid], nc_eq (nvar kid) nexp, atom_typ (nvar kid)),Parse_ast.Generated l)
- (* For informative booleans tweak the type name so that doc_typ knows that the
- constraint should be output. *)
| Typ_aux (Typ_app (Id_aux (Id "atom_bool",il), ([A_aux (A_bool _,_)] as args)),l) ->
- Some "build_ex", Typ_aux (Typ_app (Id_aux (Id "atom#bool",il), args),l)
+ Some "build_ex", ret_typ
| _ -> None, ret_typ
let is_range_from_atom env (Typ_aux (argty,_)) (Typ_aux (fnty,_)) =
@@ -1222,7 +1208,7 @@ let doc_exp, doc_let =
| Some _ ->
wrap_parens (string "build_ex" ^/^ epp)
in
- let rec construct_dep_pairs env =
+ let construct_dep_pairs ?(rawbools=false) env =
let rec aux want_parens (E_aux (e,_) as exp) (Typ_aux (t,_) as typ) =
match e,t with
| E_tuple exps, Typ_tup typs
@@ -1231,15 +1217,11 @@ let doc_exp, doc_let =
parens (separate (string ", ") (List.map2 (aux false) exps typs))
| _ ->
let typ' = expand_range_type (Env.expand_synonyms (env_of exp) typ) in
+ debug ctxt (lazy ("Constructing " ^ string_of_exp exp ^ " at type " ^ string_of_typ typ));
let build_ex, out_typ =
- match destruct_exist_plain typ' with
- | Some (kopts,nc,(Typ_aux (Typ_app (Id_aux (Id "atom_bool",_), [A_aux (A_bool atom_nc,_)]),l) as t)) -> begin
- match simplify_atom_bool l kopts nc atom_nc with
- | Bool_boring -> None, t
- | Bool_complex _ -> Some "build_ex", t
- end
- | Some (_,_,t) -> Some "build_ex", t
- | None -> None, typ'
+ match classify_ex_type ctxt (env_of exp) ~rawbools typ' with
+ | ExNone, _, _ -> None, typ'
+ | ExGeneral, _, typ' -> Some "build_ex", typ'
in
let in_typ = expand_range_type (Env.expand_synonyms (env_of exp) (typ_of exp)) in
let in_typ = match destruct_exist_plain in_typ with Some (_,_,t) -> t | None -> in_typ in
@@ -1350,14 +1332,14 @@ let doc_exp, doc_let =
begin match f with
| Id_aux (Id "and_bool", _) | Id_aux (Id "or_bool", _)
when effectful (effect_of full_exp) ->
- let informative = Util.is_some (is_auto_decomposed_exist (env_of full_exp) (typ_of full_exp)) in
+ let informative = Util.is_some (is_auto_decomposed_exist ctxt (env_of full_exp) (general_typ_of full_exp)) in
let suffix = if informative then "MP" else "M" in
let call = doc_id (append_id f suffix) in
let doc_arg exp =
let epp = expY exp in
- match is_auto_decomposed_exist (env_of exp) (typ_of exp) with
+ match is_auto_decomposed_exist ctxt (env_of exp) ~rawbools:true (general_typ_of exp) with
| Some _ ->
- if informative then epp else
+ if informative then parens (epp ^^ doc_tannot ctxt (env_of exp) true (general_typ_of exp)) else
let proj = if effectful (effect_of exp) then "projT1_m" else "projT1" in
parens (string proj ^/^ epp)
| None ->
@@ -1365,6 +1347,7 @@ let doc_exp, doc_let =
else epp
in
let epp = hang 2 (flow (break 1) (call :: List.map doc_arg args)) in
+ let epp = if informative then epp ^^ doc_tannot ctxt (env_of full_exp) true (general_typ_of full_exp) else epp in
wrap_parens epp
(* temporary hack to make the loop body a function of the temporary variables *)
| Id_aux (Id "None", _) as none -> doc_id_ctor none
@@ -1596,21 +1579,22 @@ let doc_exp, doc_let =
let ret_typ_inst =
subst_unifiers inst ret_typ
in
- let packeff,unpack,autocast,projbool =
+ let packeff,unpack,autocast =
let ann_typ = Env.expand_synonyms env (general_typ_of_annot (l,annot)) in
let ann_typ = expand_range_type ann_typ in
let ret_typ_inst = expand_range_type (Env.expand_synonyms env ret_typ_inst) in
let ret_typ_inst =
if is_no_proof_fn env f then ret_typ_inst
else snd (replace_atom_return_type ret_typ_inst) in
- let () =
+ let () =
debug ctxt (lazy (" type returned " ^ string_of_typ ret_typ_inst));
debug ctxt (lazy (" type expected " ^ string_of_typ ann_typ))
in
let unpack, in_typ =
- match ret_typ_inst with
- | Typ_aux (Typ_exist (_,_,t1),_) -> true,t1
- | t1 -> false,t1
+ if is_no_proof_fn env f then false, ret_typ_inst else
+ match classify_ex_type ctxt env ~rawbools:true ret_typ_inst with
+ | ExGeneral, _, t1 -> true,t1
+ | ExNone, _, t1 -> false,t1
in
let pack,out_typ =
match ann_typ with
@@ -1625,19 +1609,13 @@ let doc_exp, doc_let =
Typ_aux (Typ_app (_,[A_aux (A_nexp n2,_);_;_]),_) ->
not (similar_nexps ctxt env n1 n2)
| _ -> false
- in
- let projbool =
- match in_typ with
- | Typ_aux (Typ_app (Id_aux (Id "atom#bool",_),_),_) -> true
- | _ -> false
- in pack,unpack,autocast,projbool
+ in pack,unpack,autocast
in
let autocast_id, proj_id =
if effectful eff
then "autocast_m", "projT1_m"
else "autocast", "projT1" in
let epp = if unpack && not (effectful eff) then string proj_id ^/^ parens epp else epp in
- let epp = if projbool && not (effectful eff) then string "projT1" ^/^ parens epp else epp in
let epp = if autocast then string autocast_id ^^ space ^^ parens epp else epp in
let epp =
if effectful eff && packeff && not unpack
@@ -1706,9 +1684,9 @@ let doc_exp, doc_let =
debug ctxt (lazy (" on expr of type " ^ string_of_typ inner_typ));
debug ctxt (lazy (" where type expected is " ^ string_of_typ outer_typ))
in
- let outer_ex,outer_typ' = classify_ex_type outer_typ in
- let cast_ex,cast_typ' = classify_ex_type cast_typ in
- let inner_ex,inner_typ' = classify_ex_type inner_typ in
+ let outer_ex,_,outer_typ' = classify_ex_type ctxt env outer_typ in
+ let cast_ex,_,cast_typ' = classify_ex_type ctxt env ~rawbools:true cast_typ in
+ let inner_ex,_,inner_typ' = classify_ex_type ctxt env inner_typ in
let autocast =
(* Avoid using helper functions which simplify the nexps *)
is_bitvector_typ outer_typ' && is_bitvector_typ cast_typ' &&
@@ -1886,11 +1864,11 @@ let doc_exp, doc_let =
let middle =
match pat' with
| P_aux (P_id id,_)
- when Util.is_none (is_auto_decomposed_exist (env_of e1) (typ_of e1)) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e1) (typ_of e1)) &&
not (is_enum (env_of e1) id) ->
separate space [string ">>= fun"; doc_id id; bigarrow]
| P_aux (P_typ (typ, P_aux (P_id id,_)),_)
- when Util.is_none (is_auto_decomposed_exist (env_of e1) typ) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e1) typ) &&
not (is_enum (env_of e1) id) ->
separate space [string ">>= fun"; doc_id id; colon; doc_typ ctxt typ; bigarrow] | _ ->
separate space [string ">>= fun"; squote ^^ doc_pat ctxt true true (pat', typ'); bigarrow]
@@ -1899,44 +1877,39 @@ let doc_exp, doc_let =
| _ ->
let epp =
let middle =
+ let env1 = env_of e1 in
match pat with
| P_aux (P_wild,_) | P_aux (P_typ (_, P_aux (P_wild, _)), _) ->
string ">>"
| P_aux (P_id id,_)
- when Util.is_none (is_auto_decomposed_exist (env_of e1) (typ_of e1)) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e1) (typ_of e1)) &&
not (is_enum (env_of e1) id) ->
separate space [string ">>= fun"; doc_id id; bigarrow]
| P_aux (P_typ (typ, P_aux (P_id id,_)),_)
- when Util.is_none (is_auto_decomposed_exist (env_of e1) typ) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e1) typ) &&
not (is_enum (env_of e1) id) ->
separate space [string ">>= fun"; doc_id id; colon; doc_typ ctxt typ; bigarrow]
| P_aux (P_typ (typ, P_aux (P_id id,_)),_)
| P_aux (P_typ (typ, P_aux (P_var (P_aux (P_id id,_),_),_)),_)
| P_aux (P_var (P_aux (P_typ (typ, P_aux (P_id id,_)),_),_),_)
- when not (is_enum (env_of e1) id) ->
+ when not (is_enum env1 id) ->
let full_typ = (expand_range_type typ) in
- let binder = match classify_ex_type (Env.expand_synonyms (env_of e1) full_typ) with
- | ExGeneral, _ ->
+ let binder = match classify_ex_type ctxt env1 (Env.expand_synonyms env1 full_typ) with
+ | ExGeneral, _, _ ->
squote ^^ parens (separate space [string "existT"; underscore; doc_id id; underscore; colon; doc_typ ctxt typ])
- | ExNone, _ ->
+ | ExNone, _, _ ->
parens (separate space [doc_id id; colon; doc_typ ctxt typ])
in separate space [string ">>= fun"; binder; bigarrow]
| P_aux (P_id id,_) ->
let typ = typ_of e1 in
let plain_binder = squote ^^ doc_pat ctxt true true (pat, typ_of e1) in
- let binder = match classify_ex_type (Env.expand_synonyms (env_of e1) typ) with
- | ExGeneral, (Typ_aux (Typ_app (Id_aux (Id "atom_bool",_),_),_) as typ') ->
- begin match clean_typ ctxt (env_of_pat pat) typ with
- | Some typ' ->
- squote ^^ parens (separate space [string "existT"; underscore; doc_id id; underscore; colon; doc_typ ctxt typ'])
- | None -> plain_binder end
- | ExNone, typ' -> begin
+ let binder = match classify_ex_type ctxt env1 ~binding:id (Env.expand_synonyms env1 typ) with
+ | ExGeneral, _, (Typ_aux (Typ_app (Id_aux (Id "atom_bool",_),_),_) as typ') ->
+ squote ^^ parens (separate space [string "existT"; underscore; doc_id id; underscore; colon; doc_typ ctxt typ])
+ | ExNone, _, typ' -> begin
match typ' with
| Typ_aux (Typ_app (Id_aux (Id "atom_bool",_),_),_) ->
- begin match clean_typ ctxt (env_of_pat pat) typ with
- | Some typ' ->
- squote ^^ parens (separate space [string "existT"; underscore; doc_id id; underscore; colon; doc_typ ctxt typ'])
- | None -> plain_binder end
+ squote ^^ parens (separate space [string "existT"; underscore; doc_id id; underscore; colon; doc_typ ctxt typ])
| _ -> plain_binder
end
| _ -> plain_binder
@@ -1958,7 +1931,7 @@ let doc_exp, doc_let =
in
let valpp =
let env = env_of e1 in
- construct_dep_pairs env true e1 ret_typ
+ construct_dep_pairs env true e1 ret_typ ~rawbools:true
in
wrap_parens (align (separate space [string "returnm"; valpp]))
| E_sizeof nexp ->
@@ -2009,13 +1982,13 @@ let doc_exp, doc_let =
(* Prefer simple lets over patterns, because I've found Coq can struggle to
work out return types otherwise *)
| LB_val(P_aux (P_id id,_),e)
- when Util.is_none (is_auto_decomposed_exist (env_of e) (typ_of e)) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e) (typ_of e)) &&
not (is_enum (env_of e) id) ->
prefix 2 1
(separate space [string "let"; doc_id id; coloneq])
(top_exp ctxt false e)
| LB_val(P_aux (P_typ (typ,P_aux (P_id id,_)),_),e)
- when Util.is_none (is_auto_decomposed_exist (env_of e) typ) &&
+ when Util.is_none (is_auto_decomposed_exist ctxt (env_of e) typ) &&
not (is_enum (env_of e) id) ->
prefix 2 1
(separate space [string "let"; doc_id id; colon; doc_typ ctxt typ; coloneq])
@@ -2298,7 +2271,7 @@ let pat_is_plain_binder env (P_aux (p,_)) =
let demote_all_patterns env i (P_aux (p,p_annot) as pat,typ) =
match pat_is_plain_binder env pat with
| Some id ->
- if Util.is_none (is_auto_decomposed_exist env typ)
+ if Util.is_none (is_auto_decomposed_exist empty_ctxt env typ)
then (pat,typ), fun e -> e
else
(P_aux (P_id id, p_annot),typ),
@@ -2421,11 +2394,6 @@ let doc_funcl mutrec rec_opt (FCL_aux(FCL_Funcl(id, pexp), annot)) =
| Typ_aux (Typ_fn (arg_typs, ret_typ, eff),_) -> arg_typs, ret_typ, eff
| _ -> failwith ("Function " ^ string_of_id id ^ " does not have function type")
in
- let build_ex, ret_typ = replace_atom_return_type ret_typ in
- let build_ex = match classify_ex_type (Env.expand_synonyms env (expand_range_type ret_typ)) with
- | ExGeneral, _ -> Some "build_ex"
- | ExNone, _ -> build_ex
- in
let ids_to_avoid = all_ids pexp in
let bound_kids = tyvars_of_typquant tq in
let pat,guard,exp,(l,_) = destruct_pexp pexp in
@@ -2447,15 +2415,23 @@ let doc_funcl mutrec rec_opt (FCL_aux(FCL_Funcl(id, pexp), annot)) =
| Rec_aux (Rec_measure _,_) -> true, IdSet.singleton id
| _ -> false, IdSet.empty
in
- let ctxt =
+ let ctxt0 =
{ early_ret = contains_early_return exp;
kid_renames = mk_kid_renames ids_to_avoid kids_used;
kid_id_renames = kid_to_arg_rename;
bound_nvars = bound_kids;
- build_at_return = if effectful eff then build_ex else None;
+ build_at_return = None; (* filled in below *)
recursive_ids = recursive_ids;
debug = List.mem (string_of_id id) (!opt_debug_on)
} in
+ let build_ex, ret_typ = replace_atom_return_type ret_typ in
+ let build_ex = match classify_ex_type ctxt0 env (Env.expand_synonyms env (expand_range_type ret_typ)) with
+ | ExGeneral, _, _ -> Some "build_ex"
+ | ExNone, _, _ -> build_ex
+ in
+ let ctxt = { ctxt0 with
+ build_at_return = if effectful eff then build_ex else None;
+ } in
let () =
debug ctxt (lazy ("Function " ^ string_of_id id));
debug ctxt (lazy (" return type " ^ string_of_typ ret_typ));
@@ -2478,19 +2454,21 @@ let doc_funcl mutrec rec_opt (FCL_aux(FCL_Funcl(id, pexp), annot)) =
debug ctxt (lazy (" with expanded type " ^ string_of_typ exp_typ))
in
match pat_is_plain_binder env pat with
- | Some id ->
- if Util.is_none (is_auto_decomposed_exist env exp_typ) then
- parens (separate space [doc_id id; colon; doc_typ ctxt typ])
- else begin
+ | Some id -> begin
+ match classify_ex_type ctxt env ~binding:id exp_typ with
+ | ExNone, _, typ' ->
+ parens (separate space [doc_id id; colon; doc_typ ctxt typ'])
+ | ExGeneral, _, _ ->
let full_typ = (expand_range_type exp_typ) in
match destruct_exist_plain (Env.expand_synonyms env full_typ) with
| Some ([kopt], NC_aux (NC_true,_),
- Typ_aux (Typ_app (Id_aux (Id "atom",_),
+ Typ_aux (Typ_app (Id_aux (Id ("atom" | "atom_bool" as tyname),_),
[A_aux (A_nexp (Nexp_aux (Nexp_var kid,_)),_)]),_))
when Kid.compare (kopt_kid kopt) kid == 0 ->
- parens (separate space [doc_id id; colon; string "Z"])
+ let coqty = if tyname = "atom" then "Z" else "bool" in
+ parens (separate space [doc_id id; colon; string coqty])
| Some ([kopt], nc,
- Typ_aux (Typ_app (Id_aux (Id "atom",_),
+ Typ_aux (Typ_app (Id_aux (Id ("atom" | "atom_bool"),_),
[A_aux (A_nexp (Nexp_aux (Nexp_var kid,_)),_)]),_))
when Kid.compare (kopt_kid kopt) kid == 0 && not is_measured ->
(used_a_pattern := true;