@@ -207,6 +207,8 @@ and f_node =
207207 | Fpr of pr (* hr *)
208208
209209and eagerF = {
210+ eg_ml : memory ;
211+ eg_mr : memory ;
210212 eg_pr : form ;
211213 eg_sl : stmt ; (* No local program variables *)
212214 eg_fl : EcPath .xpath ;
@@ -216,6 +218,8 @@ and eagerF = {
216218}
217219
218220and equivF = {
221+ ef_ml : memory ;
222+ ef_mr : memory ;
219223 ef_pr : form ;
220224 ef_fl : EcPath .xpath ;
221225 ef_fr : EcPath .xpath ;
@@ -231,6 +235,7 @@ and equivS = {
231235 es_po : form ; }
232236
233237and sHoareF = {
238+ hf_m : memory ;
234239 hf_pr : form ;
235240 hf_f : EcPath .xpath ;
236241 hf_po : form ;
@@ -244,6 +249,7 @@ and sHoareS = {
244249
245250
246251and eHoareF = {
252+ ehf_m : memory ;
247253 ehf_pr : form ;
248254 ehf_f : EcPath .xpath ;
249255 ehf_po : form ;
@@ -257,6 +263,7 @@ and eHoareS = {
257263}
258264
259265and bdHoareF = {
266+ bhf_m : memory ;
260267 bhf_pr : form ;
261268 bhf_f : EcPath .xpath ;
262269 bhf_po : form ;
@@ -280,6 +287,309 @@ and pr = {
280287 pr_event : form ;
281288}
282289
290+ type ss_inv = {
291+ m : memory ;
292+ inv : form ;
293+ }
294+
295+ let map_ss_inv (fn : form list -> form ) (invs : ss_inv list ): ss_inv =
296+ assert (List. length invs > 0 );
297+ let m' = (List. hd invs).m in
298+ let inv = fn (List. map (fun {inv;m} -> assert (m = m'); inv) invs) in
299+ { m = m'; inv = inv }
300+
301+ let map_ss_inv1 (fn : form -> form ) (inv : ss_inv ): ss_inv =
302+ let inv' = fn inv.inv in
303+ { m = inv.m; inv = inv' }
304+
305+ let map_ss_inv2 (fn : form -> form -> form ) (inv1 : ss_inv ) (inv2 : ss_inv ): ss_inv =
306+ assert (inv1.m = inv2.m);
307+ let inv' = fn inv1.inv inv2.inv in
308+ { m = inv1.m; inv = inv' }
309+
310+ let map_ss_inv3 (fn : form -> form -> form -> form )
311+ (inv1 : ss_inv ) (inv2 : ss_inv ) (inv3 : ss_inv ): ss_inv =
312+ assert (inv1.m = inv2.m && inv2.m = inv3.m);
313+ let inv' = fn inv1.inv inv2.inv inv3.inv in
314+ { m = inv1.m; inv = inv' }
315+
316+ let map_ss_inv_destr2 (fn : form -> form * form ) (inv : ss_inv ): ss_inv * ss_inv =
317+ let inv1, inv2 = fn inv.inv in
318+ let m = inv.m in
319+ (* Everything should be boolean *)
320+ assert (inv1.f_ty = inv2.f_ty && inv1.f_ty = inv.inv.f_ty);
321+ {m;inv= inv1}, {m;inv= inv2}
322+
323+ let map_ss_inv_destr3 (fn : form -> form * form * form ) (inv : ss_inv ): ss_inv * ss_inv * ss_inv =
324+ let inv1, inv2, inv3 = fn inv.inv in
325+ let m = inv.m in
326+ (* Everything should be boolean *)
327+ assert (inv1.f_ty = inv2.f_ty && inv2.f_ty = inv3.f_ty && inv1.f_ty = inv.inv.f_ty);
328+ {m;inv= inv1}, {m;inv= inv2}, {m;inv= inv3}
329+
330+ type ts_inv = {
331+ ml : memory ;
332+ mr : memory ;
333+ inv : form ;
334+ }
335+
336+ let map_ts_inv (fn : form list -> form ) (invs : ts_inv list ): ts_inv =
337+ assert (List. length invs > 0 );
338+ let ml' = (List. hd invs).ml in
339+ let mr' = (List. hd invs).mr in
340+ let inv = fn (List. map (fun {inv;ml;mr} -> assert (ml = ml' && mr = mr'); inv) invs) in
341+ { ml = ml'; mr = mr'; inv = inv }
342+
343+ let map_ts_inv1 (fn : form -> form ) (inv : ts_inv ): ts_inv =
344+ let inv' = fn inv.inv in
345+ { ml = inv.ml; mr = inv.mr; inv = inv' }
346+
347+ let map_ts_inv2 (fn : form -> form -> form ) (inv1 : ts_inv ) (inv2 : ts_inv ): ts_inv =
348+ assert (inv1.ml = inv2.ml && inv1.mr = inv2.mr);
349+ let inv' = fn inv1.inv inv2.inv in
350+ { ml = inv1.ml; mr = inv1.mr; inv = inv' }
351+
352+ let map_ts_inv3 (fn : form -> form -> form -> form )
353+ (inv1 : ts_inv ) (inv2 : ts_inv ) (inv3 : ts_inv ): ts_inv =
354+ assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml &&
355+ inv1.mr = inv2.mr && inv2.mr = inv3.mr);
356+ let inv' = fn inv1.inv inv2.inv inv3.inv in
357+ { ml = inv1.ml; mr = inv1.mr; inv = inv' }
358+
359+ let map_ts_inv_left (fn : ss_inv list -> ss_inv ) (invs : ts_inv list ): ts_inv =
360+ assert (List. length invs > 0 );
361+ let mr' = (List. hd invs).mr in
362+ let inv = fn (List. map (fun {inv;ml;mr} -> assert (mr = mr'); {m= ml;inv}) invs) in
363+ { ml= inv.m; mr = mr'; inv = inv.inv }
364+
365+ let map_ts_inv_left1 (fn : ss_inv -> ss_inv ) (inv : ts_inv ): ts_inv =
366+ let inv' = fn {m= inv.ml; inv= inv.inv} in
367+ { ml = inv.ml; mr = inv.mr; inv = inv'.inv }
368+
369+ let map_ts_inv_left2 (fn : ss_inv -> ss_inv -> ss_inv ) (inv1 : ts_inv ) (inv2 : ts_inv ): ts_inv =
370+ assert (inv1.mr = inv2.mr);
371+ let inv' = fn {m= inv1.ml; inv= inv1.inv} {m= inv2.ml; inv= inv2.inv} in
372+ { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv }
373+
374+ let map_ts_inv_left3 (fn : ss_inv -> ss_inv -> ss_inv -> ss_inv )
375+ (inv1 : ts_inv ) (inv2 : ts_inv ) (inv3 : ts_inv ): ts_inv =
376+ assert (inv1.mr = inv2.mr && inv2.mr = inv3.mr);
377+ let inv' = fn {m= inv1.ml; inv= inv1.inv} {m= inv2.ml; inv= inv2.inv} {m= inv3.ml; inv= inv3.inv} in
378+ { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv }
379+
380+ let map_ts_inv_right (fn : ss_inv list -> ss_inv ) (invs : ts_inv list ): ts_inv =
381+ assert (List. length invs > 0 );
382+ let ml' = (List. hd invs).ml in
383+ let inv = fn (List. map (fun {inv;ml;mr} -> assert (ml = ml'); {m= mr;inv}) invs) in
384+ { ml = ml'; mr = inv.m; inv = inv.inv }
385+
386+ let map_ts_inv_right1 (fn : ss_inv -> ss_inv ) (inv : ts_inv ): ts_inv =
387+ let inv' = fn {m= inv.mr; inv= inv.inv} in
388+ { ml = inv.ml; mr = inv.mr; inv = inv'.inv }
389+
390+ let map_ts_inv_right2 (fn : ss_inv -> ss_inv -> ss_inv ) (inv1 : ts_inv ) (inv2 : ts_inv ): ts_inv =
391+ assert (inv1.ml = inv2.ml);
392+ let inv' = fn {m= inv1.mr; inv= inv1.inv} {m= inv2.mr; inv= inv2.inv} in
393+ { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv }
394+
395+ let map_ts_inv_right3 (fn : ss_inv -> ss_inv -> ss_inv -> ss_inv )
396+ (inv1 : ts_inv ) (inv2 : ts_inv ) (inv3 : ts_inv ): ts_inv =
397+ assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml);
398+ let inv' = fn {m= inv1.mr; inv= inv1.inv} {m= inv2.mr; inv= inv2.inv} {m= inv3.mr; inv= inv3.inv} in
399+ { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv }
400+
401+ let map_ts_inv_destr2 (fn : form -> form * form ) (inv : ts_inv ): ts_inv * ts_inv =
402+ let inv1, inv2 = fn inv.inv in
403+ let ml = inv.ml in
404+ let mr = inv.mr in
405+ (* Everything should be boolean *)
406+ assert (inv1.f_ty = inv2.f_ty && inv1.f_ty = inv.inv.f_ty);
407+ {ml;mr;inv= inv1}, {ml;mr;inv= inv2}
408+
409+ let map_ts_inv_destr3 (fn : form -> form * form * form ) (inv : ts_inv ) =
410+ let inv1, inv2, inv3 = fn inv.inv in
411+ let ml = inv.ml in
412+ let mr = inv.mr in
413+ (* Everything should be boolean *)
414+ assert (inv1.f_ty = inv2.f_ty && inv2.f_ty = inv3.f_ty && inv1.f_ty = inv.inv.f_ty);
415+ {ml;mr;inv= inv1}, {ml;mr;inv= inv2}, {ml;mr;inv= inv3}
416+
417+ let ts_inv_lower_left (fn : ss_inv list -> form ) (invs : ts_inv list ): ss_inv =
418+ assert (List. length invs > 0 );
419+ let mr' = (List. hd invs).mr in
420+ let inv = fn (List. map (fun {inv;ml;mr} -> assert (mr = mr'); {m= ml; inv}) invs) in
421+ { m = mr'; inv = inv }
422+
423+ let ts_inv_lower_left1 (fn : ss_inv -> form ) (inv : ts_inv ): ss_inv =
424+ let inv' = fn {m= inv.ml; inv= inv.inv} in
425+ { m = inv.mr; inv = inv' }
426+
427+ let ts_inv_lower_left2 (fn : ss_inv -> ss_inv -> form ) (inv1 : ts_inv ) inv2 =
428+ assert (inv1.mr = inv2.mr);
429+ let inv' = fn {m= inv1.ml; inv= inv1.inv} {m= inv2.ml; inv= inv2.inv} in
430+ { m = inv1.mr; inv = inv' }
431+
432+ let ts_inv_lower_left3 (fn : ss_inv -> ss_inv -> ss_inv -> form )
433+ (inv1 : ts_inv ) (inv2 : ts_inv ) (inv3 : ts_inv ): ss_inv =
434+ assert (inv1.mr = inv2.mr && inv2.mr = inv3.mr);
435+ let inv' = fn {m= inv1.ml; inv= inv1.inv} {m= inv2.ml; inv= inv2.inv} {m= inv3.ml; inv= inv3.inv} in
436+ { m = inv1.mr; inv = inv' }
437+
438+ let ts_inv_lower_right (fn : ss_inv list -> form ) (invs : ts_inv list ): ss_inv =
439+ assert (List. length invs > 0 );
440+ let ml' = (List. hd invs).ml in
441+ let inv = fn (List. map (fun {inv;ml;mr} -> assert (ml = ml'); {m= mr; inv}) invs) in
442+ { m = ml'; inv = inv }
443+
444+ let ts_inv_lower_right1 (fn : ss_inv -> form ) (inv : ts_inv ): ss_inv =
445+ let inv' = fn {m= inv.mr; inv= inv.inv} in
446+ { m = inv.ml; inv = inv' }
447+
448+ let ts_inv_lower_right2 (fn : ss_inv -> ss_inv -> form ) (inv1 : ts_inv ) inv2 =
449+ assert (inv1.ml = inv2.ml);
450+ let inv' = fn {m= inv1.mr; inv= inv1.inv} {m= inv2.mr; inv= inv2.inv} in
451+ { m = inv1.ml; inv = inv' }
452+
453+ let ts_inv_lower_right3 (fn : ss_inv -> ss_inv -> ss_inv -> form )
454+ (inv1 : ts_inv ) (inv2 : ts_inv ) (inv3 : ts_inv ): ss_inv =
455+ assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml);
456+ let inv' = fn {m= inv1.mr; inv= inv1.inv} {m= inv2.mr; inv= inv2.inv} {m= inv3.mr; inv= inv3.inv} in
457+ { m = inv1.ml; inv = inv' }
458+
459+ (* ----------------------------------------------------------------- *)
460+
461+ type inv =
462+ | Inv_ss of ss_inv
463+ | Inv_ts of ts_inv
464+
465+ (* TODO: Get rid of this after refactor *)
466+ let inv_of_inv (inv : inv ) : form =
467+ match inv with
468+ | Inv_ss ss -> ss.inv
469+ | Inv_ts ts -> ts.inv
470+
471+ let lift_ss_inv (f : ss_inv -> 'a ) : inv -> 'a =
472+ let f inv = match inv with
473+ | Inv_ss ss -> f ss
474+ | Inv_ts _ -> failwith " expected single sided invariant" in
475+ f
476+
477+ let lift_ss_inv2 (f : ss_inv -> ss_inv -> 'a ) : inv -> inv -> 'a =
478+ let f inv1 inv2 = match inv1, inv2 with
479+ | Inv_ss ss1 , Inv_ss ss2 -> f ss1 ss2
480+ | _ -> failwith " expected only single sided invariants" in
481+ f
482+
483+ let lift_ss_inv3 (f : ss_inv -> ss_inv -> ss_inv -> 'a ) : inv -> inv -> inv -> 'a =
484+ let f inv1 inv2 inv3 = match inv1, inv2, inv3 with
485+ | Inv_ss ss1 , Inv_ss ss2 , Inv_ss ss3 -> f ss1 ss2 ss3
486+ | _ -> failwith " expected only single sided invariants" in
487+ f
488+
489+ let lift_ts_inv (f : ts_inv -> 'a ) : inv -> 'a =
490+ let f inv = match inv with
491+ | Inv_ts ss -> f ss
492+ | Inv_ss _ -> failwith " expected two sided invariant" in
493+ f
494+
495+ let lift_ts_inv2 (f : ts_inv -> ts_inv -> 'a ) : inv -> inv -> 'a =
496+ let f inv1 inv2 = match inv1, inv2 with
497+ | Inv_ts ss1 , Inv_ts ss2 -> f ss1 ss2
498+ | _ -> failwith " expected only two sided invariants" in
499+ f
500+
501+ (* TODO: This should be removed after refactor is done *)
502+ let lift_inv_adapter (f : form -> 'a ) : inv -> 'a =
503+ let f inv = match inv with
504+ | Inv_ss ss -> f ss.inv
505+ | Inv_ts ts -> f ts.inv in
506+ f
507+
508+ let lift_inv_adapter2 (f : form -> form -> 'a ) : inv -> inv -> 'a =
509+ let f inv1 inv2 = match inv1, inv2 with
510+ | Inv_ss ss1 , Inv_ss ss2 -> f ss1.inv ss2.inv
511+ | Inv_ts ts1 , Inv_ts ts2 -> f ts1.inv ts2.inv
512+ | _ -> failwith " expected compatible invariants" in
513+ f
514+
515+ let ss_inv_generalize_left (inv : ss_inv ) (m : memory ) : ts_inv =
516+ { ml = m; mr = inv.m; inv = inv.inv }
517+
518+ let ss_inv_generalize_right (inv : ss_inv ) (m : memory ) : ts_inv =
519+ { ml = inv.m; mr = m; inv = inv.inv }
520+
521+ (* ----------------------------------------------------------------- *)
522+ let map_inv (fn : form list -> form ) (inv : inv list ): inv =
523+ assert (List. length inv > 0 );
524+ match List. hd inv with
525+ | Inv_ss ss' ->
526+ Inv_ss (map_ss_inv fn (List. map (function
527+ Inv_ss ss -> assert (ss.m = ss'.m); ss
528+ | _ -> failwith " expected all invariants to have same kind" ) inv))
529+ | Inv_ts ts' ->
530+ Inv_ts (map_ts_inv fn (List. map (function
531+ Inv_ts ts -> assert (ts.ml = ts'.ml && ts.mr = ts'.mr); ts
532+ | _ -> failwith " expected all invariants to have same kind" ) inv))
533+
534+ let map_inv1 (fn : form -> form ) (inv : inv ): inv =
535+ match inv with
536+ | Inv_ss ss ->
537+ Inv_ss (map_ss_inv1 fn ss)
538+ | Inv_ts ts ->
539+ Inv_ts (map_ts_inv1 fn ts)
540+
541+ let map_inv2 (fn : form -> form -> form ) (inv1 : inv ) (inv2 : inv ): inv =
542+ match inv1, inv2 with
543+ | Inv_ss ss1 , Inv_ss ss2 ->
544+ Inv_ss (map_ss_inv2 fn ss1 ss2)
545+ | Inv_ts ts1 , Inv_ts ts2 ->
546+ Inv_ts (map_ts_inv2 fn ts1 ts2)
547+ | _ ->
548+ failwith " incompatible invariants for map_inv2"
549+
550+ let map_inv3 (fn : form -> form -> form -> form )
551+ (inv1 : inv ) (inv2 : inv ) (inv3 : inv ): inv =
552+ match inv1, inv2, inv3 with
553+ | Inv_ss ss1 , Inv_ss ss2 , Inv_ss ss3 ->
554+ Inv_ss (map_ss_inv3 fn ss1 ss2 ss3)
555+ | Inv_ts ts1 , Inv_ts ts2 , Inv_ts ts3 ->
556+ Inv_ts (map_ts_inv3 fn ts1 ts2 ts3)
557+ | _ ->
558+ failwith " incompatible invariants for map_inv3"
559+
560+ (* ----------------------------------------------------------------- *)
561+ (* Accessors for program logic *)
562+ (* ----------------------------------------------------------------- *)
563+
564+ let eg_pr eg = {ml= eg.eg_ml; mr= eg.eg_mr; inv= eg.eg_pr}
565+ let eg_po eg = {ml= eg.eg_ml; mr= eg.eg_mr; inv= eg.eg_po}
566+
567+ let ef_pr ef = {ml= ef.ef_ml; mr= ef.ef_mr; inv= ef.ef_pr}
568+ let ef_po ef = {ml= ef.ef_ml; mr= ef.ef_mr; inv= ef.ef_po}
569+
570+ let es_pr es = {ml= fst es.es_ml; mr= fst es.es_mr; inv= es.es_pr}
571+ let es_po es = {ml= fst es.es_ml; mr= fst es.es_mr; inv= es.es_po}
572+
573+ let hf_pr hf = {m= hf.hf_m; inv= hf.hf_pr}
574+ let hf_po hf = {m= hf.hf_m; inv= hf.hf_po}
575+
576+ let hs_pr hs = {m= fst hs.hs_m; inv= hs.hs_pr}
577+ let hs_po hs = {m= fst hs.hs_m; inv= hs.hs_po}
578+
579+ let ehf_pr ehf = {m= ehf.ehf_m; inv= ehf.ehf_pr}
580+ let ehf_po ehf = {m= ehf.ehf_m; inv= ehf.ehf_po}
581+
582+ let ehs_pr ehs = {m= fst ehs.ehs_m; inv= ehs.ehs_pr}
583+ let ehs_po ehs = {m= fst ehs.ehs_m; inv= ehs.ehs_po}
584+
585+ let bhf_pr bhf = {m= bhf.bhf_m; inv= bhf.bhf_pr}
586+ let bhf_po bhf = {m= bhf.bhf_m; inv= bhf.bhf_po}
587+ let bhf_bd bhf = {m= bhf.bhf_m; inv= bhf.bhf_bd}
588+
589+ let bhs_pr bhs = {m= fst bhs.bhs_m; inv= bhs.bhs_pr}
590+ let bhs_po bhs = {m= fst bhs.bhs_m; inv= bhs.bhs_po}
591+ let bhs_bd bhs = {m= fst bhs.bhs_m; inv= bhs.bhs_bd}
592+
283593(* ----------------------------------------------------------------- *)
284594(* Equality, hash, and fv *)
285595(* ----------------------------------------------------------------- *)
0 commit comments