@@ -112,8 +112,41 @@ it directly calls this checker and pass the post as the loop_ensures argument he
112112
113113*)
114114
115- # push - options " --fuel 0 --ifuel 0 --z3rlimit_factor 64 "
115+ # push - options " --fuel 0 --ifuel 0 --z3rlimit_factor 72 "
116116module RT = FStar.Reflection.Typing
117+
118+ # push - options " --fuel 1 --ifuel 1"
119+ let rec compute_meas_infos ( g : env ) ( pre : term ) ( ms : list term )
120+ : T. Tac ( list ( term & term & universe ))
121+ = match ms with
122+ | [] -> []
123+ | m :: rest ->
124+ let m' = purify_term g { ctxt_now = pre ; ctxt_old = Some pre } m in
125+ let (| _ , _ , ty , (| u , _ |), _ |) = compute_term_type_and_u g m' in
126+ ( m , ty , u ) :: compute_meas_infos g pre rest
127+
128+ let rec build_tuple_info ( infos : list ( term & term & universe ))
129+ : T. Tac ( term & term & universe & ( term -> term -> term ))
130+ = match infos with
131+ | [( m , ty , u )] -> ( m , ty , u , mk_precedes u ty )
132+ | ( m , ty , u ) :: rest ->
133+ let ( m_rest , ty_rest , u_rest , mk_dec_rest ) = build_tuple_info rest in
134+ let ty_tup = mk_tuple2 u u_rest ty ty_rest in
135+ let m_tup = mk_mktuple2 u u_rest ty ty_rest m m_rest in
136+ let mk_dec_tup ( new_m : term ) ( old_m : term ) : term =
137+ let new_hd = mk_fst u u_rest ty ty_rest new_m in
138+ let old_hd = mk_fst u u_rest ty ty_rest old_m in
139+ let new_tl = mk_snd u u_rest ty ty_rest new_m in
140+ let old_tl = mk_snd u u_rest ty ty_rest old_m in
141+ let precedes_hd = mk_precedes u ty new_hd old_hd in
142+ let eq_hd = mk_eq2 u ty new_hd old_hd in
143+ let rest_dec = mk_dec_rest new_tl old_tl in
144+ tm_l_or precedes_hd ( tm_l_and eq_hd rest_dec )
145+ in
146+ ( m_tup , ty_tup , u , mk_dec_tup )
147+ | _ -> ( unit_const , tm_unit , u0 , mk_precedes u0 tm_unit )
148+ # pop - options
149+
117150let check_while
118151 ( g : env )
119152 ( pre : term )
@@ -156,20 +189,27 @@ let check_while
156189 if loop_requires ` eq_tm ` tm_l_true then inv else
157190 ( inv ` tm_star ` tm_pure ( mk_loop_requires_marker loop_requires )) in
158191 let x_meas : nvar = mk_ppname_no_range " meas" , fresh g in
159- let u_meas , ty_meas , meas , is_tot =
192+ let u_meas , ty_meas , meas_val , is_tot , mk_dec =
160193 match meas with
161- | None -> u0 , tm_unit , unit_const , false
162- | Some meas ->
194+ | [] -> u0 , tm_unit , unit_const , false , mk_precedes u0 tm_unit
195+ | [ meas ] ->
163196 let meas' = purify_term g { ctxt_now = pre ; ctxt_old = Some pre } meas in
164197 let (| _ , _ , ty , (| u , _ |), _ |) = compute_term_type_and_u g meas' in
165- u , ty , meas , true
198+ u , ty , meas , true , mk_precedes u ty
199+ | _ ->
200+ let meas_infos = compute_meas_infos g pre meas in
201+ let ( meas_val , _ty_approx , _u_approx , mk_dec ) = build_tuple_info meas_infos in
202+ let meas_val' = purify_term g { ctxt_now = pre ; ctxt_old = Some pre } meas_val in
203+ let (| _ , _ , ty , (| u , _ |), _ |) = compute_term_type_and_u g meas_val' in
204+ u , ty , meas_val , true , mk_dec
166205 in
206+ let dec_formula = mk_dec ( tm_bvar { bv_index = 0 ; bv_ppname = fst x_meas }) ( term_of_nvar x_meas ) in
167207 let inv_range = term_range inv in
168208 let g_meas = push_binding g ( snd x_meas ) ( fst x_meas ) ty_meas in
169209 let inv = dfst <|
170210 purify_and_check_spec ( push_context " invariant" inv_range g_meas )
171211 { ctxt_now = pre ; ctxt_old = Some pre }
172- ( inv ` tm_star ` tm_pure ( mk_eq2 u_meas ty_meas ( term_of_nvar x_meas ) meas ))
212+ ( inv ` tm_star ` tm_pure ( mk_eq2 u_meas ty_meas ( term_of_nvar x_meas ) meas_val ))
173213 in
174214 let loop_pre0 = tm_exists_sl u_meas ( as_binder ty_meas ) ( close_term inv ( snd x_meas )) in
175215 let (| g0 , remaining , k |) = Pulse.Checker.Prover. prove t . range g pre loop_pre0 false in
@@ -242,7 +282,7 @@ let check_while
242282 (| t , c , typ |) in
243283
244284 let body_pre_open = post_cond . post in
245- let body_post_typing : tot_typing g2 ( comp_post ( comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open )) tm_slprop = RU. magic () in
285+ let body_post_typing : tot_typing g2 ( comp_post ( comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open )) tm_slprop = RU. magic () in
246286 let body_ph : post_hint_for_env g2 = inv_as_post_hint body_post_typing in
247287 assert body_ph . ret_ty == tm_unit ;
248288 let x = fresh g2 in
@@ -258,21 +298,21 @@ let check_while
258298 let (| cond , comp_cond , cond_typing |) = r_cond in
259299 let (| body , comp_body , body_typing |) = apply_checker_result_k r_body ppname_default in
260300 assert ( comp_cond == ( comp_while_cond inv body_pre_open ));
261- assert ( comp_post comp_body == comp_post ( comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open ));
262- assert ( comp_pre comp_body == comp_pre ( comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open ));
263- assert ( comp_u comp_body == comp_u ( comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open ));
264- assert ( comp_res comp_body == comp_res ( comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open ));
265- assert ( comp_body == comp_while_body u_meas ty_meas is_tot x_meas inv body_pre_open );
301+ assert ( comp_post comp_body == comp_post ( comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open ));
302+ assert ( comp_pre comp_body == comp_pre ( comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open ));
303+ assert ( comp_u comp_body == comp_u ( comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open ));
304+ assert ( comp_res comp_body == comp_res ( comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open ));
305+ assert ( comp_body == comp_while_body u_meas ty_meas is_tot dec_formula x_meas inv body_pre_open );
266306 let inv_typing2 : tot_typing g2 inv tm_slprop = RU. magic () in
267307
268- let while = wtag ( Some STT ) ( Tm_While { invariant = inv ; loop_requires = tm_unknown ; meas = None ; condition = cond ; body }) in
308+ let while = wtag ( Some STT ) ( Tm_While { invariant = inv ; loop_requires = tm_unknown ; meas = [] ; condition = cond ; body }) in
269309 let typ_meas : universe_of g1' ty_meas u_meas = RU. magic () in
270310 assume ~( snd x_meas ` Set. mem ` freevars_st cond );
271311 assume ~( snd x_meas ` Set. mem ` freevars_st body );
272312 let d : st_typing g1' while ( comp_while u_meas ty_meas x_meas inv body_pre_open ) =
273313 let h = RU. magic () in
274314 T_While g1' inv body_pre_open cond body
275- u_meas ty_meas typ_meas is_tot
315+ u_meas ty_meas typ_meas is_tot dec_formula
276316 x_meas g2
277317 inv_typing2 h cond_typing body_typing
278318 in
0 commit comments