diff --git a/src/ecAst.ml b/src/ecAst.ml index 2b30c3568..d9c9c2b1f 100644 --- a/src/ecAst.ml +++ b/src/ecAst.ml @@ -207,6 +207,8 @@ and f_node = | Fpr of pr (* hr *) and eagerF = { + eg_ml : memory; + eg_mr : memory; eg_pr : form; eg_sl : stmt; (* No local program variables *) eg_fl : EcPath.xpath; @@ -216,6 +218,8 @@ and eagerF = { } and equivF = { + ef_ml : memory; + ef_mr : memory; ef_pr : form; ef_fl : EcPath.xpath; ef_fr : EcPath.xpath; @@ -231,6 +235,7 @@ and equivS = { es_po : form; } and sHoareF = { + hf_m : memory; hf_pr : form; hf_f : EcPath.xpath; hf_po : form; @@ -244,6 +249,7 @@ and sHoareS = { and eHoareF = { + ehf_m : memory; ehf_pr : form; ehf_f : EcPath.xpath; ehf_po : form; @@ -257,6 +263,7 @@ and eHoareS = { } and bdHoareF = { + bhf_m : memory; bhf_pr : form; bhf_f : EcPath.xpath; bhf_po : form; @@ -273,13 +280,320 @@ and bdHoareS = { bhs_bd : form; } +and ss_inv = { + m : memory; + inv : form; +} + and pr = { pr_mem : memory; pr_fun : EcPath.xpath; pr_args : form; - pr_event : form; + pr_event : ss_inv; +} + +let map_ss_inv ?m (fn: form list -> form) (invs: ss_inv list): ss_inv = + let m' = match m with + | Some m -> m + | None -> (List.hd invs).m in + let inv = fn (List.map (fun {inv;m} -> assert (m = m'); inv) invs) in + { m = m'; inv = inv } + +let map_ss_inv1 (fn: form -> form) (inv: ss_inv): ss_inv = + let inv' = fn inv.inv in + { m = inv.m; inv = inv' } + +let map_ss_inv2 (fn: form -> form -> form) (inv1: ss_inv) (inv2: ss_inv): ss_inv = + assert (inv1.m = inv2.m); + let inv' = fn inv1.inv inv2.inv in + { m = inv1.m; inv = inv' } + +let map_ss_inv3 (fn: form -> form -> form -> form) + (inv1: ss_inv) (inv2: ss_inv) (inv3: ss_inv): ss_inv = + assert (inv1.m = inv2.m && inv2.m = inv3.m); + let inv' = fn inv1.inv inv2.inv inv3.inv in + { m = inv1.m; inv = inv' } + +let map_ss_inv_destr2 (fn: form -> form * form) (inv: ss_inv): ss_inv * ss_inv = + let inv1, inv2 = fn inv.inv in + let m = inv.m in + (* Everything should be boolean *) + assert (inv1.f_ty = inv2.f_ty && inv1.f_ty = inv.inv.f_ty); + {m;inv=inv1}, {m;inv=inv2} + +let map_ss_inv_destr3 (fn: form -> form * form * form) (inv: ss_inv): ss_inv * ss_inv * ss_inv = + let inv1, inv2, inv3 = fn inv.inv in + let m = inv.m in + (* Everything should be boolean *) + assert (inv1.f_ty = inv2.f_ty && inv2.f_ty = inv3.f_ty && inv1.f_ty = inv.inv.f_ty); + {m;inv=inv1}, {m;inv=inv2}, {m;inv=inv3} + +type ts_inv = { + ml : memory; + mr : memory; + inv : form; } +let map_ts_inv ?ml ?mr (fn: form list -> form) (invs: ts_inv list): ts_inv = + let ml' = match ml with + | Some m -> m + | None -> (List.hd invs).ml in + let mr' = match mr with + | Some m -> m + | None -> (List.hd invs).mr in + let inv = fn (List.map (fun {inv;ml;mr} -> assert (ml = ml' && mr = mr'); inv) invs) in + { ml = ml'; mr = mr'; inv = inv } + +let map_ts_inv1 (fn: form -> form) (inv: ts_inv): ts_inv = + let inv' = fn inv.inv in + { ml = inv.ml; mr = inv.mr; inv = inv' } + +let map_ts_inv2 (fn: form -> form -> form) (inv1: ts_inv) (inv2: ts_inv): ts_inv = + assert (inv1.ml = inv2.ml && inv1.mr = inv2.mr); + let inv' = fn inv1.inv inv2.inv in + { ml = inv1.ml; mr = inv1.mr; inv = inv' } + +let map_ts_inv3 (fn: form -> form -> form -> form) + (inv1: ts_inv) (inv2: ts_inv) (inv3: ts_inv): ts_inv = + assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml && + inv1.mr = inv2.mr && inv2.mr = inv3.mr); + let inv' = fn inv1.inv inv2.inv inv3.inv in + { ml = inv1.ml; mr = inv1.mr; inv = inv' } + +let map_ts_inv_left (fn: ss_inv list -> ss_inv) (invs: ts_inv list): ts_inv = + assert (List.length invs > 0); + let mr' = (List.hd invs).mr in + let inv = fn (List.map (fun {inv;ml;mr} -> assert (mr = mr'); {m=ml;inv}) invs) in + { ml=inv.m; mr = mr'; inv = inv.inv } + +let map_ts_inv_left1 (fn: ss_inv -> ss_inv) (inv: ts_inv): ts_inv = + let inv' = fn {m=inv.ml; inv=inv.inv} in + { ml = inv.ml; mr = inv.mr; inv = inv'.inv } + +let map_ts_inv_left2 (fn: ss_inv -> ss_inv -> ss_inv) (inv1: ts_inv) (inv2: ts_inv): ts_inv = + assert (inv1.mr = inv2.mr); + let inv' = fn {m=inv1.ml; inv=inv1.inv} {m=inv2.ml; inv=inv2.inv} in + { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv } + +let map_ts_inv_left3 (fn: ss_inv -> ss_inv -> ss_inv -> ss_inv) + (inv1: ts_inv) (inv2: ts_inv) (inv3: ts_inv): ts_inv = + assert (inv1.mr = inv2.mr && inv2.mr = inv3.mr); + let inv' = fn {m=inv1.ml; inv=inv1.inv} {m=inv2.ml; inv=inv2.inv} {m=inv3.ml; inv=inv3.inv} in + { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv } + +let map_ts_inv_right (fn: ss_inv list -> ss_inv) (invs: ts_inv list): ts_inv = + assert (List.length invs > 0); + let ml' = (List.hd invs).ml in + let inv = fn (List.map (fun {inv;ml;mr} -> assert (ml = ml'); {m=mr;inv}) invs) in + { ml = ml'; mr = inv.m; inv = inv.inv } + +let map_ts_inv_right1 (fn: ss_inv -> ss_inv) (inv: ts_inv): ts_inv = + let inv' = fn {m=inv.mr; inv=inv.inv} in + { ml = inv.ml; mr = inv.mr; inv = inv'.inv } + +let map_ts_inv_right2 (fn: ss_inv -> ss_inv -> ss_inv) (inv1: ts_inv) (inv2: ts_inv): ts_inv = + assert (inv1.ml = inv2.ml); + let inv' = fn {m=inv1.mr; inv=inv1.inv} {m=inv2.mr; inv=inv2.inv} in + { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv } + +let map_ts_inv_right3 (fn: ss_inv -> ss_inv -> ss_inv -> ss_inv) + (inv1: ts_inv) (inv2: ts_inv) (inv3: ts_inv): ts_inv = + assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml); + let inv' = fn {m=inv1.mr; inv=inv1.inv} {m=inv2.mr; inv=inv2.inv} {m=inv3.mr; inv=inv3.inv} in + { ml = inv1.ml; mr = inv1.mr; inv = inv'.inv } + +let map_ts_inv_destr2 (fn: form -> form * form) (inv: ts_inv): ts_inv * ts_inv = + let inv1, inv2 = fn inv.inv in + let ml = inv.ml in + let mr = inv.mr in + (* Everything should be boolean *) + assert (inv1.f_ty = inv2.f_ty && inv1.f_ty = inv.inv.f_ty); + {ml;mr;inv=inv1}, {ml;mr;inv=inv2} + +let map_ts_inv_destr3 (fn: form -> form * form * form) (inv: ts_inv) = + let inv1, inv2, inv3 = fn inv.inv in + let ml = inv.ml in + let mr = inv.mr in + (* Everything should be boolean *) + assert (inv1.f_ty = inv2.f_ty && inv2.f_ty = inv3.f_ty && inv1.f_ty = inv.inv.f_ty); + {ml;mr;inv=inv1}, {ml;mr;inv=inv2}, {ml;mr;inv=inv3} + +let ts_inv_lower_left (fn: ss_inv list -> form) (invs: ts_inv list): ss_inv = + assert (List.length invs > 0); + let mr' = (List.hd invs).mr in + let inv = fn (List.map (fun {inv;ml;mr} -> assert (mr = mr'); {m=ml; inv}) invs) in + { m = mr'; inv = inv } + +let ts_inv_lower_left1 (fn: ss_inv -> form) (inv: ts_inv): ss_inv = + let inv' = fn {m=inv.ml; inv=inv.inv} in + { m = inv.mr; inv = inv' } + +let ts_inv_lower_left2 (fn: ss_inv -> ss_inv -> form) (inv1: ts_inv) inv2 = + assert (inv1.mr = inv2.mr); + let inv' = fn {m=inv1.ml; inv=inv1.inv} {m=inv2.ml; inv=inv2.inv} in + { m = inv1.mr; inv = inv' } + +let ts_inv_lower_left3 (fn: ss_inv -> ss_inv -> ss_inv -> form) + (inv1: ts_inv) (inv2: ts_inv) (inv3: ts_inv): ss_inv = + assert (inv1.mr = inv2.mr && inv2.mr = inv3.mr); + let inv' = fn {m=inv1.ml; inv=inv1.inv} {m=inv2.ml; inv=inv2.inv} {m=inv3.ml; inv=inv3.inv} in + { m = inv1.mr; inv = inv' } + +let ts_inv_lower_right (fn: ss_inv list -> form) (invs: ts_inv list): ss_inv = + assert (List.length invs > 0); + let ml' = (List.hd invs).ml in + let inv = fn (List.map (fun {inv;ml;mr} -> assert (ml = ml'); {m=mr; inv}) invs) in + { m = ml'; inv = inv } + +let ts_inv_lower_right1 (fn: ss_inv -> form) (inv: ts_inv): ss_inv = + let inv' = fn {m=inv.mr; inv=inv.inv} in + { m = inv.ml; inv = inv' } + +let ts_inv_lower_right2 (fn: ss_inv -> ss_inv -> form) (inv1: ts_inv) inv2 = + assert (inv1.ml = inv2.ml); + let inv' = fn {m=inv1.mr; inv=inv1.inv} {m=inv2.mr; inv=inv2.inv} in + { m = inv1.ml; inv = inv' } + +let ts_inv_lower_right3 (fn: ss_inv -> ss_inv -> ss_inv -> form) + (inv1: ts_inv) (inv2: ts_inv) (inv3: ts_inv): ss_inv = + assert (inv1.ml = inv2.ml && inv2.ml = inv3.ml); + let inv' = fn {m=inv1.mr; inv=inv1.inv} {m=inv2.mr; inv=inv2.inv} {m=inv3.mr; inv=inv3.inv} in + { m = inv1.ml; inv = inv' } + +(* ----------------------------------------------------------------- *) + +type inv = + | Inv_ss of ss_inv + | Inv_ts of ts_inv + +(* TODO: Get rid of this after refactor *) +let inv_of_inv (inv: inv) : form = + match inv with + | Inv_ss ss -> ss.inv + | Inv_ts ts -> ts.inv + +let lift_ss_inv (f: ss_inv -> 'a) : inv -> 'a = + let f inv = match inv with + | Inv_ss ss -> f ss + | Inv_ts _ -> failwith "expected single sided invariant" in + f + +let lift_ss_inv2 (f: ss_inv -> ss_inv -> 'a) : inv -> inv -> 'a = + let f inv1 inv2 = match inv1, inv2 with + | Inv_ss ss1, Inv_ss ss2 -> f ss1 ss2 + | _ -> failwith "expected only single sided invariants" in + f + +let lift_ss_inv3 (f: ss_inv -> ss_inv -> ss_inv -> 'a) : inv -> inv -> inv -> 'a = + let f inv1 inv2 inv3 = match inv1, inv2, inv3 with + | Inv_ss ss1, Inv_ss ss2, Inv_ss ss3 -> f ss1 ss2 ss3 + | _ -> failwith "expected only single sided invariants" in + f + +let lift_ts_inv (f: ts_inv -> 'a) : inv -> 'a = + let f inv = match inv with + | Inv_ts ss -> f ss + | Inv_ss _ -> failwith "expected two sided invariant" in + f + +let lift_ts_inv2 (f: ts_inv -> ts_inv -> 'a) : inv -> inv -> 'a = + let f inv1 inv2 = match inv1, inv2 with + | Inv_ts ss1, Inv_ts ss2 -> f ss1 ss2 + | _ -> failwith "expected only two sided invariants" in + f + +(* TODO: This should be removed after refactor is done *) +let lift_inv_adapter (f: form -> 'a) : inv -> 'a = + let f inv = match inv with + | Inv_ss ss -> f ss.inv + | Inv_ts ts -> f ts.inv in + f + +let lift_inv_adapter2 (f: form -> form -> 'a) : inv -> inv -> 'a = + let f inv1 inv2 = match inv1, inv2 with + | Inv_ss ss1, Inv_ss ss2 -> f ss1.inv ss2.inv + | Inv_ts ts1, Inv_ts ts2 -> f ts1.inv ts2.inv + | _ -> failwith "expected compatible invariants" in + f + +let ss_inv_generalize_left (inv: ss_inv) (m: memory) : ts_inv = + { ml = m; mr = inv.m; inv = inv.inv } + +let ss_inv_generalize_right (inv: ss_inv) (m: memory) : ts_inv = + { ml = inv.m; mr = m; inv = inv.inv } + +(* ----------------------------------------------------------------- *) +let map_inv (fn: form list -> form) (inv: inv list): inv = + assert (List.length inv > 0); + match List.hd inv with + | Inv_ss ss' -> + Inv_ss (map_ss_inv fn (List.map (function + Inv_ss ss -> assert (ss.m = ss'.m); ss + | _ -> failwith "expected all invariants to have same kind") inv)) + | Inv_ts ts' -> + Inv_ts (map_ts_inv fn (List.map (function + Inv_ts ts -> assert (ts.ml = ts'.ml && ts.mr = ts'.mr); ts + | _ -> failwith "expected all invariants to have same kind") inv)) + +let map_inv1 (fn: form -> form) (inv: inv): inv = + match inv with + | Inv_ss ss -> + Inv_ss (map_ss_inv1 fn ss) + | Inv_ts ts -> + Inv_ts (map_ts_inv1 fn ts) + +let map_inv2 (fn: form -> form -> form) (inv1: inv) (inv2: inv): inv = + match inv1, inv2 with + | Inv_ss ss1, Inv_ss ss2 -> + Inv_ss (map_ss_inv2 fn ss1 ss2) + | Inv_ts ts1, Inv_ts ts2 -> + Inv_ts (map_ts_inv2 fn ts1 ts2) + | _ -> + failwith "incompatible invariants for map_inv2" + +let map_inv3 (fn: form -> form -> form -> form) + (inv1: inv) (inv2: inv) (inv3: inv): inv = + match inv1, inv2, inv3 with + | Inv_ss ss1, Inv_ss ss2, Inv_ss ss3 -> + Inv_ss (map_ss_inv3 fn ss1 ss2 ss3) + | Inv_ts ts1, Inv_ts ts2, Inv_ts ts3 -> + Inv_ts (map_ts_inv3 fn ts1 ts2 ts3) + | _ -> + failwith "incompatible invariants for map_inv3" + +(* ----------------------------------------------------------------- *) +(* Accessors for program logic *) +(* ----------------------------------------------------------------- *) + +let eg_pr eg = {ml=eg.eg_ml; mr=eg.eg_mr; inv=eg.eg_pr} +let eg_po eg = {ml=eg.eg_ml; mr=eg.eg_mr; inv=eg.eg_po} + +let ef_pr ef = {ml=ef.ef_ml; mr=ef.ef_mr; inv=ef.ef_pr} +let ef_po ef = {ml=ef.ef_ml; mr=ef.ef_mr; inv=ef.ef_po} + +let es_pr es = {ml=fst es.es_ml; mr=fst es.es_mr; inv=es.es_pr} +let es_po es = {ml=fst es.es_ml; mr=fst es.es_mr; inv=es.es_po} + +let hf_pr hf = {m=hf.hf_m; inv=hf.hf_pr} +let hf_po hf = {m=hf.hf_m; inv=hf.hf_po} + +let hs_pr hs = {m=fst hs.hs_m; inv=hs.hs_pr} +let hs_po hs = {m=fst hs.hs_m; inv=hs.hs_po} + +let ehf_pr ehf = {m=ehf.ehf_m; inv=ehf.ehf_pr} +let ehf_po ehf = {m=ehf.ehf_m; inv=ehf.ehf_po} + +let ehs_pr ehs = {m=fst ehs.ehs_m; inv=ehs.ehs_pr} +let ehs_po ehs = {m=fst ehs.ehs_m; inv=ehs.ehs_po} + +let bhf_pr bhf = {m=bhf.bhf_m; inv=bhf.bhf_pr} +let bhf_po bhf = {m=bhf.bhf_m; inv=bhf.bhf_po} +let bhf_bd bhf = {m=bhf.bhf_m; inv=bhf.bhf_bd} + +let bhs_pr bhs = {m=fst bhs.bhs_m; inv=bhs.bhs_pr} +let bhs_po bhs = {m=fst bhs.bhs_m; inv=bhs.bhs_po} +let bhs_bd bhs = {m=fst bhs.bhs_m; inv=bhs.bhs_bd} + (* ----------------------------------------------------------------- *) (* Equality, hash, and fv *) (* ----------------------------------------------------------------- *) @@ -568,6 +882,8 @@ let me_hash (mem, Lmt_concrete mt) = (EcIdent.id_hash mem) (Why3.Hashcons.combine_option lmt_hash mt) +let mem_hash: memory -> _ = EcIdent.id_hash + let mem_equal = EcIdent.id_equal let me_equal_gen ty_equal (m1,mt1) (m2,mt2) = @@ -619,6 +935,7 @@ let hf_equal hf1 hf2 = f_equal hf1.hf_pr hf2.hf_pr && f_equal hf1.hf_po hf2.hf_po && EcPath.x_equal hf1.hf_f hf2.hf_f + && mem_equal hf1.hf_m hf2.hf_m let hs_equal hs1 hs2 = f_equal hs1.hs_pr hs2.hs_pr @@ -630,6 +947,7 @@ let ehf_equal hf1 hf2 = f_equal hf1.ehf_pr hf2.ehf_pr && f_equal hf1.ehf_po hf2.ehf_po && EcPath.x_equal hf1.ehf_f hf2.ehf_f + && mem_equal hf1.ehf_m hf2.ehf_m let ehs_equal hs1 hs2 = f_equal hs1.ehs_pr hs2.ehs_pr @@ -643,6 +961,7 @@ let bhf_equal bhf1 bhf2 = && EcPath.x_equal bhf1.bhf_f bhf2.bhf_f && bhf1.bhf_cmp = bhf2.bhf_cmp && f_equal bhf1.bhf_bd bhf2.bhf_bd + && mem_equal bhf1.bhf_m bhf2.bhf_m let bhs_equal bhs1 bhs2 = f_equal bhs1.bhs_pr bhs2.bhs_pr @@ -657,6 +976,8 @@ let eqf_equal ef1 ef2 = && f_equal ef1.ef_po ef2.ef_po && EcPath.x_equal ef1.ef_fl ef2.ef_fl && EcPath.x_equal ef1.ef_fr ef2.ef_fr + && mem_equal ef1.ef_ml ef2.ef_ml + && mem_equal ef1.ef_mr ef2.ef_mr let eqs_equal es1 es2 = f_equal es1.es_pr es2.es_pr @@ -673,17 +994,20 @@ let egf_equal eg1 eg2 = && EcPath.x_equal eg1.eg_fl eg2.eg_fl && EcPath.x_equal eg1.eg_fr eg2.eg_fr && s_equal eg1.eg_sr eg2.eg_sr + && mem_equal eg1.eg_ml eg2.eg_ml + && mem_equal eg1.eg_mr eg2.eg_mr let pr_equal pr1 pr2 = EcIdent.id_equal pr1.pr_mem pr2.pr_mem && EcPath.x_equal pr1.pr_fun pr2.pr_fun - && f_equal pr1.pr_event pr2.pr_event + && f_equal pr1.pr_event.inv pr2.pr_event.inv && f_equal pr1.pr_args pr2.pr_args + && mem_equal pr1.pr_event.m pr2.pr_event.m (* -------------------------------------------------------------------- *) let hf_hash hf = - Why3.Hashcons.combine2 - (f_hash hf.hf_pr) (f_hash hf.hf_po) (EcPath.x_hash hf.hf_f) + Why3.Hashcons.combine3 + (f_hash hf.hf_pr) (f_hash hf.hf_po) (EcPath.x_hash hf.hf_f) (mem_hash hf.hf_m) let hs_hash hs = Why3.Hashcons.combine3 @@ -692,9 +1016,9 @@ let hs_hash hs = (me_hash hs.hs_m) let ehf_hash hf = - Why3.Hashcons.combine2 + Why3.Hashcons.combine3 (f_hash hf.ehf_pr) (f_hash hf.ehf_po) - (EcPath.x_hash hf.ehf_f) + (EcPath.x_hash hf.ehf_f) (mem_hash hf.ehf_m) let ehs_hash hs = Why3.Hashcons.combine3 @@ -704,7 +1028,7 @@ let ehs_hash hs = let bhf_hash bhf = Why3.Hashcons.combine_list f_hash - (Why3.Hashcons.combine (hcmp_hash bhf.bhf_cmp) (EcPath.x_hash bhf.bhf_f)) + (Why3.Hashcons.combine2 (hcmp_hash bhf.bhf_cmp) (EcPath.x_hash bhf.bhf_f) (mem_hash bhf.bhf_m)) [bhf.bhf_pr;bhf.bhf_po;bhf.bhf_bd] let bhs_hash bhs = @@ -716,9 +1040,10 @@ let bhs_hash bhs = [bhs.bhs_pr;bhs.bhs_po;bhs.bhs_bd] let ef_hash ef = - Why3.Hashcons.combine3 - (f_hash ef.ef_pr) (f_hash ef.ef_po) - (EcPath.x_hash ef.ef_fl) (EcPath.x_hash ef.ef_fr) + Why3.Hashcons.combine_list f_hash + (Why3.Hashcons.combine3 (EcPath.x_hash ef.ef_fl) (EcPath.x_hash ef.ef_fr) + (mem_hash ef.ef_ml) (mem_hash ef.ef_mr)) + [ef.ef_pr;ef.ef_po] let es_hash es = Why3.Hashcons.combine3 @@ -730,17 +1055,19 @@ let es_hash es = (s_hash es.es_sr)) let eg_hash eg = - Why3.Hashcons.combine3 - (f_hash eg.eg_pr) (f_hash eg.eg_po) - (Why3.Hashcons.combine (s_hash eg.eg_sl) (EcPath.x_hash eg.eg_fl)) - (Why3.Hashcons.combine (s_hash eg.eg_sr) (EcPath.x_hash eg.eg_fr)) + Why3.Hashcons.combine_list f_hash + (Why3.Hashcons.combine3 + (mem_hash eg.eg_ml) (mem_hash eg.eg_mr) + (Why3.Hashcons.combine (s_hash eg.eg_sl) (EcPath.x_hash eg.eg_fl)) + (Why3.Hashcons.combine (s_hash eg.eg_sr) (EcPath.x_hash eg.eg_fr))) + [eg.eg_pr; eg.eg_po] let pr_hash pr = Why3.Hashcons.combine3 (EcIdent.id_hash pr.pr_mem) (EcPath.x_hash pr.pr_fun) (f_hash pr.pr_args) - (f_hash pr.pr_event) + (Why3.Hashcons.combine (f_hash pr.pr_event.inv) (mem_hash pr.pr_event.m)) (* ----------------------------------------------------------------- *) @@ -1110,7 +1437,7 @@ module Hsform = Why3.Hashcons.Make (struct (fv_union (s_fv eg.eg_sl) (s_fv eg.eg_sr)) | Fpr pr -> - let fve = Mid.remove mhr (f_fv pr.pr_event) in + let fve = Mid.remove pr.pr_event.m (f_fv pr.pr_event.inv) in let fv = EcPath.x_fv fve pr.pr_fun in fv_union (f_fv pr.pr_args) (fv_add pr.pr_mem fv) diff --git a/src/ecAst.mli b/src/ecAst.mli index 53c542bdc..68f07e068 100644 --- a/src/ecAst.mli +++ b/src/ecAst.mli @@ -201,60 +201,87 @@ and f_node = | Fpr of pr (* hr *) +(* We use the alert system for privacy because we want to + permit access in *some* instances, and the other fields are fine *) and eagerF = { + eg_ml : memory; + eg_mr : memory; eg_pr : form; + (*[@alert priv_pl "Use the accessor function `eg_pr` instead of the field"]*) eg_sl : stmt; (* No local program variables *) eg_fl : EcPath.xpath; eg_fr : EcPath.xpath; eg_sr : stmt; (* No local program variables *) eg_po : form + (*[@alert priv_pl "Use the accessor function `es_po` instead of the field"]*) } and equivF = { + ef_ml : memory; + ef_mr : memory; ef_pr : form; + (*[@alert priv_pl "Use the accessor function `ef_pr` instead of the field"]*) ef_fl : EcPath.xpath; ef_fr : EcPath.xpath; ef_po : form; + (*[@alert priv_pl "Use the accessor function `ef_po` instead of the field"]*) } and equivS = { es_ml : memenv; es_mr : memenv; es_pr : form; + (*[@alert priv_pl "Use the accessor function `es_pr` instead of the field"]*) es_sl : stmt; es_sr : stmt; - es_po : form; } + es_po : form; + (*[@alert priv_pl "Use the accessor function `es_po` instead of the field"]*) +} and sHoareF = { + hf_m : memory; hf_pr : form; + [@alert priv_pl "Use the accessor function `hf_pr` instead of the field"] hf_f : EcPath.xpath; hf_po : form; + [@alert priv_pl "Use the accessor function `hf_pr` instead of the field"] } and sHoareS = { hs_m : memenv; hs_pr : form; + (*[@alert priv_pl "Use the accessor function `hs_pr` instead of the field"]*) hs_s : stmt; - hs_po : form; } + hs_po : form; + (*[@alert priv_pl "Use the accessor function `hs_po` instead of the field"]*) +} and eHoareF = { + ehf_m : memory; ehf_pr : form; + (*[@alert priv_pl "Use the accessor function `ehf_pr` instead of the field"]*) ehf_f : EcPath.xpath; ehf_po : form; + (*[@alert priv_pl "Use the accessor function `ehf_po` instead of the field"]*) } and eHoareS = { ehs_m : memenv; ehs_pr : form; + (*[@alert priv_pl "Use the accessor function `ehs_pr` instead of the field"]*) ehs_s : stmt; ehs_po : form; + (*[@alert priv_pl "Use the accessor function `ehs_po` instead of the field"]*) } and bdHoareF = { + bhf_m : memory; bhf_pr : form; + (*[@alert priv_pl "Use the accessor function `bhf_pr` instead of the field"]*) bhf_f : EcPath.xpath; bhf_po : form; + (*[@alert priv_pl "Use the accessor function `bhf_po` instead of the field"]*) bhf_cmp : hoarecmp; bhf_bd : form; } @@ -262,19 +289,126 @@ and bdHoareF = { and bdHoareS = { bhs_m : memenv; bhs_pr : form; + (*[@alert priv_pl "Use the accessor function `bhs_pr` instead of the field"]*) bhs_s : stmt; bhs_po : form; + (*[@alert priv_pl "Use the accessor function `bhs_po` instead of the field"]*) bhs_cmp : hoarecmp; bhs_bd : form; } +and ss_inv = { + m : memory; + inv : form; +} + and pr = { pr_mem : memory; pr_fun : EcPath.xpath; pr_args : form; - pr_event : form; + pr_event : ss_inv; +} + + +val map_ss_inv : ?m:memory -> (form list -> form) -> ss_inv list -> ss_inv +val map_ss_inv1 : (form -> form) -> ss_inv -> ss_inv +val map_ss_inv2 : (form -> form -> form) -> ss_inv -> ss_inv -> ss_inv +val map_ss_inv3 : (form -> form -> form -> form) -> ss_inv -> ss_inv -> ss_inv -> ss_inv + +val map_ss_inv_destr2 : (form -> form * form) -> ss_inv -> ss_inv * ss_inv +val map_ss_inv_destr3 : (form -> form * form * form) -> ss_inv -> ss_inv * ss_inv * ss_inv + +type ts_inv = { + ml : memory; + mr : memory; + inv : form; } +val map_ts_inv : ?ml:memory -> ?mr:memory -> (form list -> form) -> ts_inv list -> ts_inv +val map_ts_inv1 : (form -> form) -> ts_inv -> ts_inv +val map_ts_inv2 : (form -> form -> form) -> ts_inv -> ts_inv -> ts_inv +val map_ts_inv3 : (form -> form -> form -> form) -> ts_inv -> ts_inv -> ts_inv -> ts_inv + +val map_ts_inv_left : (ss_inv list -> ss_inv) -> ts_inv list -> ts_inv +val map_ts_inv_left1 : (ss_inv -> ss_inv) -> ts_inv -> ts_inv +val map_ts_inv_left2 : (ss_inv -> ss_inv -> ss_inv) -> ts_inv -> ts_inv -> ts_inv +val map_ts_inv_left3 : (ss_inv -> ss_inv -> ss_inv -> ss_inv) -> + ts_inv -> ts_inv -> ts_inv -> ts_inv + +val map_ts_inv_right : (ss_inv list -> ss_inv) -> ts_inv list -> ts_inv +val map_ts_inv_right1 : (ss_inv -> ss_inv) -> ts_inv -> ts_inv +val map_ts_inv_right2 : (ss_inv -> ss_inv -> ss_inv) -> ts_inv -> ts_inv -> ts_inv +val map_ts_inv_right3 : (ss_inv -> ss_inv -> ss_inv -> ss_inv) -> + ts_inv -> ts_inv -> ts_inv -> ts_inv + +val map_ts_inv_destr2 : (form -> form * form) -> ts_inv -> ts_inv * ts_inv +val map_ts_inv_destr3 : (form -> form * form * form) -> ts_inv -> ts_inv * ts_inv * ts_inv + +(* -------------------------------------------------------------------- *) +(* Lowering tactics *) +(* -------------------------------------------------------------------- *) + +val ts_inv_lower_left : (ss_inv list -> form) -> ts_inv list -> ss_inv +val ts_inv_lower_left1 : (ss_inv -> form) -> ts_inv -> ss_inv +val ts_inv_lower_left2 : (ss_inv -> ss_inv -> form) -> ts_inv -> ts_inv -> ss_inv +val ts_inv_lower_left3 : (ss_inv -> ss_inv -> ss_inv -> form) -> + ts_inv -> ts_inv -> ts_inv -> ss_inv + +val ts_inv_lower_right : (ss_inv list -> form) -> ts_inv list -> ss_inv +val ts_inv_lower_right1 : (ss_inv -> form) -> ts_inv -> ss_inv +val ts_inv_lower_right2 : (ss_inv -> ss_inv -> form) -> ts_inv -> ts_inv -> ss_inv +val ts_inv_lower_right3 : (ss_inv -> ss_inv -> ss_inv -> form) -> + ts_inv -> ts_inv -> ts_inv -> ss_inv + +(* -------------------------------------------------------------------- *) +(* Invariants *) +(* -------------------------------------------------------------------- *) + +type inv = + | Inv_ss of ss_inv + | Inv_ts of ts_inv + +val inv_of_inv : inv -> form + +val lift_ss_inv : (ss_inv -> 'a) -> inv -> 'a +val lift_ss_inv2 : (ss_inv -> ss_inv -> 'a) -> inv -> inv -> 'a +val lift_ss_inv3 : (ss_inv -> ss_inv -> ss_inv -> 'a) -> inv -> inv -> inv -> 'a +val lift_ts_inv : (ts_inv -> 'a) -> inv -> 'a +val lift_ts_inv2 : (ts_inv -> ts_inv -> 'a) -> inv -> inv -> 'a +val lift_inv_adapter : (form -> 'a) -> inv -> 'a +val lift_inv_adapter2 : (form -> form -> 'a) -> inv -> inv -> 'a + +val ss_inv_generalize_left : ss_inv -> memory -> ts_inv +val ss_inv_generalize_right : ss_inv -> memory -> ts_inv + +val map_inv : (form list -> form) -> inv list -> inv +val map_inv1 : (form -> form) -> inv -> inv +val map_inv2 : (form -> form -> form) -> inv -> inv -> inv +val map_inv3 : (form -> form -> form -> form) -> inv -> inv -> inv -> inv + +val eg_pr : eagerF -> ts_inv +val eg_po : eagerF -> ts_inv +val ef_pr : equivF -> ts_inv +val ef_po : equivF -> ts_inv +val es_pr : equivS -> ts_inv +val es_po : equivS -> ts_inv +val hf_pr : sHoareF -> ss_inv +val hf_po : sHoareF -> ss_inv +val hs_pr : sHoareS -> ss_inv +val hs_po : sHoareS -> ss_inv +val ehf_pr : eHoareF -> ss_inv +val ehf_po : eHoareF -> ss_inv +val ehs_pr : eHoareS -> ss_inv +val ehs_po : eHoareS -> ss_inv +val bhf_pr : bdHoareF -> ss_inv +val bhf_po : bdHoareF -> ss_inv +val bhf_bd : bdHoareF -> ss_inv +val bhs_pr : bdHoareS -> ss_inv +val bhs_po : bdHoareS -> ss_inv +val bhs_bd : bdHoareS -> ss_inv + +(* -------------------------------------------------------------------- *) + type 'a equality = 'a -> 'a -> bool type 'a hash = 'a -> int type 'a fv = 'a -> int EcIdent.Mid.t diff --git a/src/ecCallbyValue.ml b/src/ecCallbyValue.ml index aee423acb..44f3da432 100644 --- a/src/ecCallbyValue.ml +++ b/src/ecCallbyValue.ml @@ -7,6 +7,7 @@ open EcEnv open EcFol open EcReduction open EcBaseLogic +open EcMemory module BI = EcBigInt (* -------------------------------------------------------------------- *) @@ -297,7 +298,7 @@ and try_reduce_fixdef subst bds cargs) subst bds pargs in - let body = EcFol.form_of_expr EcFol.mhr body in + let body = EcFol.form_of_expr body in let body = Tvar.f_subst ~freshen:true (List.map fst op.EcDecl.op_tparams) tys body in @@ -457,7 +458,7 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = if st.st_ri.modpath then EcEnv.NormMp.norm_pvar st.st_env pv else pv in - app_red st (f_pvar pv f.f_ty m) args + app_red st (f_pvar pv f.f_ty m).inv args | Fop _ -> app_red st (Subst.subst s f) args @@ -479,11 +480,12 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = | FhoareF hf -> assert (Args.isempty args); - assert (not (Subst.has_mem s mhr)); - let hf_pr = norm st s hf.hf_pr in - let hf_po = norm st s hf.hf_po in + assert (not (Subst.has_mem s hf.hf_m)); + let hf_pr = norm st s hf.hf_pr [@alert "-priv_pl"] in + let hf_po = norm st s hf.hf_po [@alert "-priv_pl"] in let hf_f = norm_xfun st s hf.hf_f in - f_hoareF_r { hf_pr; hf_f; hf_po } + let (m,_) = norm_me s (abstract hf.hf_m) in + f_hoareF {m;inv=hf_pr} hf_f {m;inv=hf_po} | FhoareS hs -> assert (Args.isempty args); @@ -492,7 +494,8 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let hs_po = norm st s hs.hs_po in let hs_s = norm_stmt s hs.hs_s in let hs_m = norm_me s hs.hs_m in - f_hoareS_r { hs_pr; hs_po; hs_s; hs_m } + let m = fst hs_m in + f_hoareS (snd hs_m) {m;inv=hs_pr} hs_s {m;inv=hs_po} | FeHoareF hf -> assert (Args.isempty args); @@ -500,7 +503,8 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let ehf_pr = norm st s hf.ehf_pr in let ehf_po = norm st s hf.ehf_po in let ehf_f = norm_xfun st s hf.ehf_f in - f_eHoareF_r { ehf_pr; ehf_f; ehf_po; } + let (m,_) = norm_me s (abstract hf.ehf_m) in + f_eHoareF {m;inv=ehf_pr} ehf_f {m;inv=ehf_po} | FeHoareS hs -> assert (Args.isempty args); @@ -508,17 +512,18 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let ehs_pr = norm st s hs.ehs_pr in let ehs_po = norm st s hs.ehs_po in let ehs_s = norm_stmt s hs.ehs_s in - let ehs_m = norm_me s hs.ehs_m in - f_eHoareS_r { ehs_pr; ehs_po; ehs_s; ehs_m } + let (m,mt) = norm_me s hs.ehs_m in + f_eHoareS mt {m;inv=ehs_pr} ehs_s {m;inv=ehs_po} | FbdHoareF hf -> assert (Args.isempty args); - assert (not (Subst.has_mem s mhr)); + assert (not (Subst.has_mem s hf.bhf_m)); let bhf_pr = norm st s hf.bhf_pr in let bhf_po = norm st s hf.bhf_po in let bhf_f = norm_xfun st s hf.bhf_f in let bhf_bd = norm st s hf.bhf_bd in - f_bdHoareF_r { hf with bhf_pr; bhf_po; bhf_f; bhf_bd } + let (m,_) = norm_me s (abstract hf.bhf_m) in + f_bdHoareF {m;inv=bhf_pr} bhf_f {m;inv=bhf_po} hf.bhf_cmp {m;inv=bhf_bd} | FbdHoareS bhs -> assert (Args.isempty args); @@ -527,18 +532,20 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let bhs_po = norm st s bhs.bhs_po in let bhs_s = norm_stmt s bhs.bhs_s in let bhs_bd = norm st s bhs.bhs_bd in - let bhs_m = norm_me s bhs.bhs_m in - f_bdHoareS_r { bhs with bhs_m; bhs_pr; bhs_po; bhs_s; bhs_bd } + let (m,mt) = norm_me s bhs.bhs_m in + f_bdHoareS mt {m;inv=bhs_pr} bhs_s {m;inv=bhs_po} bhs.bhs_cmp {m;inv=bhs_bd} | FequivF ef -> assert (Args.isempty args); - assert (not (Subst.has_mem s mleft)); - assert (not (Subst.has_mem s mright)); + assert (not (Subst.has_mem s ef.ef_ml)); + assert (not (Subst.has_mem s ef.ef_mr)); let ef_pr = norm st s ef.ef_pr in let ef_po = norm st s ef.ef_po in let ef_fl = norm_xfun st s ef.ef_fl in let ef_fr = norm_xfun st s ef.ef_fr in - f_equivF_r {ef_pr; ef_fl; ef_fr; ef_po } + let (ml,_) = norm_me s (abstract ef.ef_ml) in + let (mr,_) = norm_me s (abstract ef.ef_mr) in + f_equivF {ml;mr;inv=ef_pr} ef_fl ef_fr {ml;mr;inv=ef_po} | FequivS es -> assert (Args.isempty args); @@ -548,9 +555,9 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let es_po = norm st s es.es_po in let es_sl = norm_stmt s es.es_sl in let es_sr = norm_stmt s es.es_sr in - let es_ml = norm_me s es.es_ml in - let es_mr = norm_me s es.es_mr in - f_equivS_r {es_ml; es_mr; es_pr; es_sl; es_sr; es_po } + let (ml,mlt) = norm_me s es.es_ml in + let (mr,mrt) = norm_me s es.es_mr in + f_equivS mlt mrt {ml;mr;inv=es_pr} es_sl es_sr {ml;mr;inv=es_po} | FeagerF eg -> assert (Args.isempty args); @@ -562,7 +569,9 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let eg_fr = norm_xfun st s eg.eg_fr in let eg_sl = norm_stmt s eg.eg_sl in let eg_sr = norm_stmt s eg.eg_sr in - f_eagerF_r {eg_pr; eg_sl; eg_fl; eg_fr; eg_sr; eg_po } + let (ml,_) = norm_me s (abstract eg.eg_ml) in + let (mr,_) = norm_me s (abstract eg.eg_mr) in + f_eagerF {ml;mr;inv=eg_pr} eg_sl eg_fl eg_fr eg_sr {ml;mr;inv=eg_po} | Fpr pr -> assert (Args.isempty args); @@ -570,8 +579,9 @@ and cbv (st : state) (s : subst) (f : form) (args : args) : form = let pr_mem = Subst.subst_m s pr.pr_mem in let pr_fun = norm_xfun st s pr.pr_fun in let pr_args = norm st s pr.pr_args in - let pr_event = norm st s pr.pr_event in - f_pr_r { pr_mem; pr_fun; pr_args; pr_event; } + let pr_event = norm st s pr.pr_event.inv in + let (m,_) = norm_me s (abstract pr.pr_event.m) in + f_pr pr_mem pr_fun pr_args {m;inv=pr_event} (* -------------------------------------------------------------------- *) (* FIXME : initialize the subst with let in hyps *) diff --git a/src/ecCoreFol.ml b/src/ecCoreFol.ml index 962125360..2ba61e66c 100644 --- a/src/ecCoreFol.ml +++ b/src/ecCoreFol.ml @@ -173,13 +173,13 @@ let f_app f args ty = (* -------------------------------------------------------------------- *) let f_local x ty = mk_form (Flocal x) ty -let f_pvar x ty m = mk_form (Fpvar(x, m)) ty +let f_pvar x ty m = {m;inv=mk_form (Fpvar(x, m)) ty} let f_pvloc v m = f_pvar (pv_loc v.v_name) v.v_type m let f_pvarg ty m = f_pvar pv_arg ty m let f_pvlocs vs menv = List.map (fun v -> f_pvloc v menv) vs -let f_glob m mem = mk_form (Fglob (m, mem)) (tglob m) +let f_glob m mem = {m=mem;inv=mk_form (Fglob (m, mem)) (tglob m)} (* -------------------------------------------------------------------- *) let f_tt = f_op EcCoreLib.CI_Unit.p_tt [] tunit @@ -274,53 +274,95 @@ let f_eqs fs1 fs2 = let f_hoareS_r hs = mk_form (FhoareS hs) tbool let f_hoareF_r hf = mk_form (FhoareF hf) tbool -let f_hoareS hs_m hs_pr hs_s hs_po = - f_hoareS_r { hs_m; hs_pr; hs_s; hs_po; } +let f_hoareS hs_mt hs_pr hs_s hs_po = + assert (hs_pr.m = hs_po.m); + f_hoareS_r { hs_m=(hs_pr.m, hs_mt); hs_pr=hs_pr.inv; hs_s; + hs_po=hs_po.inv; } [@alert "-priv_pl"] -let f_hoareF hf_pr hf_f hf_po = - f_hoareF_r { hf_pr; hf_f; hf_po; } +let f_hoareF pr hf_f po = + assert (pr.m = po.m); + f_hoareF_r { hf_m=pr.m; hf_pr=pr.inv; hf_f; hf_po=po.inv; } [@alert "-priv_pl"] (* -------------------------------------------------------------------- *) let f_eHoareS_r hs = mk_form (FeHoareS hs) tbool let f_eHoareF_r hf = mk_form (FeHoareF hf) tbool -let f_eHoareS ehs_m ehs_pr ehs_s ehs_po = - f_eHoareS_r { ehs_m; ehs_pr; ehs_s; ehs_po; } +let f_eHoareS ehs_mt ehs_pr ehs_s ehs_po = + assert (ehs_pr.m = ehs_po.m); + f_eHoareS_r { ehs_m=(ehs_pr.m, ehs_mt); ehs_pr=ehs_pr.inv; ehs_s; + ehs_po=ehs_po.inv; } [@alert "-priv_pl"] + +let f_eHoareF_old ehf_pr ehf_f ehf_po = + f_eHoareF_r { ehf_m=mhr; ehf_pr; ehf_f; ehf_po; } let f_eHoareF ehf_pr ehf_f ehf_po = - f_eHoareF_r { ehf_pr; ehf_f; ehf_po; } + assert (ehf_pr.m = ehf_po.m); + f_eHoareF_r { ehf_m=ehf_pr.m; ehf_pr=ehf_pr.inv; ehf_f; ehf_po=ehf_po.inv; } [@alert "-priv_pl"] + +(* -------------------------------------------------------------------- *) + +let f_eHoare ehf_pr ehf_f ehf_po = + assert (ehf_pr.m = ehf_po.m); + f_eHoareF_r { ehf_m=ehf_pr.m; ehf_pr=ehf_pr.inv; ehf_f; ehf_po=ehf_po.inv; } [@alert "-priv_pl"] (* -------------------------------------------------------------------- *) let f_bdHoareS_r bhs = mk_form (FbdHoareS bhs) tbool let f_bdHoareF_r bhf = mk_form (FbdHoareF bhf) tbool -let f_bdHoareS bhs_m bhs_pr bhs_s bhs_po bhs_cmp bhs_bd = +let f_bdHoareS_old bhs_m bhs_pr bhs_s bhs_po bhs_cmp bhs_bd = f_bdHoareS_r { bhs_m; bhs_pr; bhs_s; bhs_po; bhs_cmp; bhs_bd; } +let f_bdHoareS bhs_mt bhs_pr bhs_s bhs_po bhs_cmp bhs_bd = + assert (bhs_pr.m = bhs_po.m && bhs_bd.m = bhs_po.m); + f_bdHoareS_r { bhs_m=(bhs_pr.m,bhs_mt); bhs_pr=bhs_pr.inv; bhs_s; + bhs_po=bhs_po.inv; bhs_cmp; bhs_bd=bhs_bd.inv; } [@alert "-priv_pl"] + let f_bdHoareF bhf_pr bhf_f bhf_po bhf_cmp bhf_bd = - f_bdHoareF_r { bhf_pr; bhf_f; bhf_po; bhf_cmp; bhf_bd; } + assert (bhf_pr.m = bhf_po.m && bhf_bd.m = bhf_po.m); + f_bdHoareF_r { bhf_m=bhf_pr.m; bhf_pr=bhf_pr.inv; bhf_f; bhf_po=bhf_po.inv; + bhf_cmp; bhf_bd=bhf_bd.inv; } [@alert "-priv_pl"] + +let f_bdHoareF_old bhf_pr bhf_f bhf_po bhf_cmp bhf_bd = + f_bdHoareF_r { bhf_m=mhr; bhf_pr; bhf_f; bhf_po; bhf_cmp; bhf_bd; } (* -------------------------------------------------------------------- *) let f_equivS_r es = mk_form (FequivS es) tbool let f_equivF_r ef = mk_form (FequivF ef) tbool -let f_equivS es_ml es_mr es_pr es_sl es_sr es_po = +let f_equivS_old es_ml es_mr es_pr es_sl es_sr es_po = f_equivS_r { es_ml; es_mr; es_pr; es_sl; es_sr; es_po; } -let f_equivF ef_pr ef_fl ef_fr ef_po = - f_equivF_r{ ef_pr; ef_fl; ef_fr; ef_po; } +let f_equivS es_mtl es_mtr es_pr es_sl es_sr es_po = + assert (es_pr.ml = es_po.ml && es_pr.mr = es_po.mr); + let es_ml, es_mr = (es_pr.ml, es_mtl), (es_pr.mr, es_mtr) in + f_equivS_r { es_ml; es_mr; es_pr=es_pr.inv; + es_sl; es_sr; es_po=es_po.inv; } [@alert "-priv_pl"] + +(* -------------------------------------------------------------------- *) + +let f_equivF_old ef_pr ef_fl ef_fr ef_po = + f_equivF_r{ ef_ml=mleft; ef_mr=mright; ef_pr; ef_fl; ef_fr; ef_po; } + +let f_equivF pr ef_fl ef_fr po = + assert (pr.ml = po.ml && pr.mr = po.mr); + f_equivF_r { ef_ml=pr.ml; ef_mr=pr.mr; ef_pr=pr.inv; ef_fl; ef_fr; ef_po=po.inv; } (* -------------------------------------------------------------------- *) let f_eagerF_r eg = mk_form (FeagerF eg) tbool +let f_eagerF_old eg_pr eg_sl eg_fl eg_fr eg_sr eg_po = + f_eagerF_r { eg_ml=mleft; eg_mr=mright; eg_pr; eg_sl; eg_fl; eg_fr; eg_sr; eg_po; } + let f_eagerF eg_pr eg_sl eg_fl eg_fr eg_sr eg_po = - f_eagerF_r { eg_pr; eg_sl; eg_fl; eg_fr; eg_sr; eg_po; } + assert (eg_pr.ml = eg_po.ml && eg_pr.mr = eg_po.mr); + f_eagerF_r { eg_ml=eg_pr.ml; eg_mr=eg_pr.mr; eg_pr=eg_pr.inv; + eg_sl; eg_fl; eg_fr; eg_sr; eg_po=eg_po.inv; } [@alert "-priv_pl"] (* -------------------------------------------------------------------- *) let f_pr_r pr = mk_form (Fpr pr) treal -let f_pr pr_mem pr_fun pr_args pr_event = +let f_pr pr_mem pr_fun pr_args (pr_event: ss_inv) = f_pr_r { pr_mem; pr_fun; pr_args; pr_event; } (* -------------------------------------------------------------------- *) @@ -432,7 +474,7 @@ let f_map gt g fp = | Fpvar (id, s) -> let ty' = gt fp.f_ty in - f_pvar id ty' s + (f_pvar id ty' s).inv | Fop (p, tys) -> let tys' = List.Smart.map gt tys in @@ -455,9 +497,9 @@ let f_map gt g fp = f_proj f' i ty' | FhoareF hf -> - let pr' = g hf.hf_pr in - let po' = g hf.hf_po in - f_hoareF_r { hf with hf_pr = pr'; hf_po = po'; } + let pr' = map_ss_inv1 g (hf_pr hf) in + let po' = map_ss_inv1 g (hf_po hf) in + f_hoareF pr' hf.hf_f po' | FhoareS hs -> let pr' = g hs.hs_pr in @@ -503,8 +545,8 @@ let f_map gt g fp = | Fpr pr -> let args' = g pr.pr_args in - let ev' = g pr.pr_event in - f_pr_r { pr with pr_args = args'; pr_event = ev'; } + let ev' = g pr.pr_event.inv in + f_pr_r { pr with pr_args = args'; pr_event = {m=pr.pr_event.m; inv=ev'}; } (* -------------------------------------------------------------------- *) let f_iter g f = @@ -523,7 +565,7 @@ let f_iter g f = | Ftuple es -> List.iter g es | Fproj (e, _) -> g e - | FhoareF hf -> g hf.hf_pr; g hf.hf_po + | FhoareF hf -> g (hf_pr hf).inv; g (hf_po hf).inv | FhoareS hs -> g hs.hs_pr; g hs.hs_po | FeHoareF hf -> g hf.ehf_pr; g hf.ehf_po | FeHoareS hs -> g hs.ehs_pr; g hs.ehs_po @@ -532,7 +574,7 @@ let f_iter g f = | FequivF ef -> g ef.ef_pr; g ef.ef_po | FequivS es -> g es.es_pr; g es.es_po | FeagerF eg -> g eg.eg_pr; g eg.eg_po - | Fpr pr -> g pr.pr_args; g pr.pr_event + | Fpr pr -> g pr.pr_args; g pr.pr_event.inv (* -------------------------------------------------------------------- *) @@ -552,7 +594,7 @@ let form_exists g f = | Ftuple es -> List.exists g es | Fproj (e, _) -> g e - | FhoareF hf -> g hf.hf_pr || g hf.hf_po + | FhoareF hf -> g (hf_pr hf).inv || g (hf_po hf).inv | FhoareS hs -> g hs.hs_pr || g hs.hs_po | FeHoareF hf -> g hf.ehf_pr || g hf.ehf_po | FeHoareS hs -> g hs.ehs_pr || g hs.ehs_po @@ -561,7 +603,7 @@ let form_exists g f = | FequivF ef -> g ef.ef_pr || g ef.ef_po | FequivS es -> g es.es_pr || g es.es_po | FeagerF eg -> g eg.eg_pr || g eg.eg_po - | Fpr pr -> g pr.pr_args || g pr.pr_event + | Fpr pr -> g pr.pr_args || g pr.pr_event.inv (* -------------------------------------------------------------------- *) let form_forall g f = @@ -580,14 +622,14 @@ let form_forall g f = | Ftuple es -> List.for_all g es | Fproj (e, _) -> g e - | FhoareF hf -> g hf.hf_pr && g hf.hf_po + | FhoareF hf -> g (hf_pr hf).inv && g (hf_po hf).inv | FhoareS hs -> g hs.hs_pr && g hs.hs_po | FbdHoareF bhf -> g bhf.bhf_pr && g bhf.bhf_po | FbdHoareS bhs -> g bhs.bhs_pr && g bhs.bhs_po | FequivF ef -> g ef.ef_pr && g ef.ef_po | FequivS es -> g es.es_pr && g es.es_po | FeagerF eg -> g eg.eg_pr && g eg.eg_po - | Fpr pr -> g pr.pr_args && g pr.pr_event + | Fpr pr -> g pr.pr_args && g pr.pr_event.inv | FeHoareF hf -> g hf.ehf_pr && g hf.ehf_po | FeHoareS hs -> g hs.ehs_pr && g hs.ehs_po @@ -809,6 +851,16 @@ let destr_imp = destr_app2 ~name:"imp" is_op_imp let destr_iff = destr_app2 ~name:"iff" is_op_iff let destr_eq = destr_app2 ~name:"eq" is_op_eq +let destr_and_ts_inv inv = + let c1 = map_ts_inv1 (fun po -> fst (destr_and po)) inv in + let c2 = map_ts_inv1 (fun po -> snd (destr_and po)) inv in + (c1, c2) + +let destr_and_ss_inv inv = + let c1 = map_ss_inv1 (fun po -> fst (destr_and po)) inv in + let c2 = map_ss_inv1 (fun po -> snd (destr_and po)) inv in + (c1, c2) + let destr_and3 f = try let c1, (c2, c3) = snd_map destr_and (destr_and f) @@ -898,7 +950,8 @@ let equantif_of_quantif (qt : quantif) : equantif = | Lexists -> `EExists (* -------------------------------------------------------------------- *) -let rec form_of_expr mem (e : expr) = + +let rec form_of_expr_r ?m (e : expr) = match e.e_node with | Eint n -> f_int n @@ -907,44 +960,53 @@ let rec form_of_expr mem (e : expr) = f_local id e.e_ty | Evar pv -> - f_pvar pv e.e_ty mem + begin + match m with + | None -> failwith "expecting memory" + | Some m -> (f_pvar pv e.e_ty m).inv + end | Eop (op, tys) -> f_op op tys e.e_ty | Eapp (ef, es) -> - f_app (form_of_expr mem ef) (List.map (form_of_expr mem) es) e.e_ty + f_app (form_of_expr_r ?m ef) (List.map (form_of_expr_r ?m) es) e.e_ty | Elet (lpt, e1, e2) -> - f_let lpt (form_of_expr mem e1) (form_of_expr mem e2) + f_let lpt (form_of_expr_r ?m e1) (form_of_expr_r ?m e2) | Etuple es -> - f_tuple (List.map (form_of_expr mem) es) + f_tuple (List.map (form_of_expr_r ?m) es) | Eproj (e1, i) -> - f_proj (form_of_expr mem e1) i e.e_ty + f_proj (form_of_expr_r ?m e1) i e.e_ty | Eif (e1, e2, e3) -> - let e1 = form_of_expr mem e1 in - let e2 = form_of_expr mem e2 in - let e3 = form_of_expr mem e3 in + let e1 = form_of_expr_r ?m e1 in + let e2 = form_of_expr_r ?m e2 in + let e3 = form_of_expr_r ?m e3 in f_if e1 e2 e3 | Ematch (b, fs, ty) -> - let b' = form_of_expr mem b in - let fs' = List.map (form_of_expr mem) fs in + let b' = form_of_expr_r ?m b in + let fs' = List.map (form_of_expr_r ?m) fs in f_match b' fs' ty | Equant (qt, b, e) -> let b = List.map (fun (x, ty) -> (x, GTty ty)) b in - let e = form_of_expr mem e in + let e = form_of_expr_r ?m e in f_quant (quantif_of_equantif qt) b e +let form_of_expr e = form_of_expr_r e + +let ss_inv_of_expr m (e : expr) = + {m;inv=form_of_expr_r ~m e} (* -------------------------------------------------------------------- *) exception CannotTranslate -let expr_of_form mh f = +let expr_of_ss_inv f = + let mh, f = f.m, f.inv in let rec aux fp = match fp.f_node with | Fint z -> e_int z @@ -986,6 +1048,43 @@ let expr_of_form mh f = in aux f +let expr_of_form f = + let rec aux fp = + match fp.f_node with + | Fint z -> e_int z + | Flocal x -> e_local x fp.f_ty + + | Fop (p, tys) -> e_op p tys fp.f_ty + | Fapp (f, fs) -> e_app (aux f) (List.map aux fs) fp.f_ty + | Ftuple fs -> e_tuple (List.map aux fs) + | Fproj (f, i) -> e_proj (aux f) i fp.f_ty + + | Fif (c, f1, f2) -> + e_if (aux c) (aux f1) (aux f2) + + | Fmatch (c, bs, ty) -> + e_match (aux c) (List.map aux bs) ty + + | Flet (lp, f1, f2) -> + e_let lp (aux f1) (aux f2) + + | Fquant (kd, bds, f) -> + e_quantif (equantif_of_quantif kd) (List.map auxbd bds) (aux f) + + | Fpvar _ | Fglob _ + | FhoareF _ | FhoareS _ + | FeHoareF _ | FeHoareS _ + | FbdHoareF _ | FbdHoareS _ + | FequivF _ | FequivS _ + | FeagerF _ | Fpr _ -> raise CannotTranslate + + and auxbd ((x, bd) : binding) = + match bd with + | GTty ty -> (x, ty) + | _ -> raise CannotTranslate + + in aux f + (* -------------------------------------------------------------------- *) (* A predicate on memory: λ mem. -> pred *) type mem_pr = EcMemory.memory * form diff --git a/src/ecCoreFol.mli b/src/ecCoreFol.mli index 07f61851d..55d1b4129 100644 --- a/src/ecCoreFol.mli +++ b/src/ecCoreFol.mli @@ -92,10 +92,10 @@ val kind_of_gty: gty -> [`Form | `Mem | `Mod] (* soft-constructors - common leaves *) val f_local : EcIdent.t -> EcTypes.ty -> form -val f_pvar : EcTypes.prog_var -> EcTypes.ty -> memory -> form -val f_pvarg : EcTypes.ty -> memory -> form -val f_pvloc : variable -> memory -> form -val f_glob : EcIdent.t -> memory -> form +val f_pvar : EcTypes.prog_var -> EcTypes.ty -> memory -> ss_inv +val f_pvarg : EcTypes.ty -> memory -> ss_inv +val f_pvloc : variable -> memory -> ss_inv +val f_glob : EcIdent.t -> memory -> ss_inv (* soft-constructors - common formulas constructors *) val f_op : path -> EcTypes.ty list -> EcTypes.ty -> form @@ -113,43 +113,36 @@ val f_lambda : bindings -> form -> form val f_forall_mems : (EcIdent.t * memtype) list -> form -> form -(* soft-constructors - hoare *) -val f_hoareF_r : sHoareF -> form -val f_hoareS_r : sHoareS -> form +val f_hoareF : ss_inv -> xpath -> ss_inv -> form +val f_hoareS : memtype -> ss_inv -> stmt -> ss_inv -> form -val f_hoareF : form -> xpath -> form -> form -val f_hoareS : memenv -> form -> stmt -> form -> form +val f_eHoareF_old : form -> xpath -> form -> form +val f_eHoareF : ss_inv -> xpath -> ss_inv -> form +val f_eHoareS : memtype -> ss_inv -> EcCoreModules.stmt -> ss_inv -> form -(* soft-constructors - expected hoare *) -val f_eHoareF_r : eHoareF -> form -val f_eHoareS_r : eHoareS -> form - -val f_eHoareF : form -> xpath -> form -> form -val f_eHoareS : memenv -> form -> EcCoreModules.stmt -> form -> form +(* soft-constructors - eager *) (* soft-constructors - bd hoare *) val hoarecmp_opp : hoarecmp -> hoarecmp -val f_bdHoareF_r : bdHoareF -> form -val f_bdHoareS_r : bdHoareS -> form - -val f_bdHoareF : form -> xpath -> form -> hoarecmp -> form -> form -val f_bdHoareS : memenv -> form -> stmt -> form -> hoarecmp -> form -> form +val f_bdHoareF : ss_inv -> xpath -> ss_inv -> hoarecmp -> ss_inv -> form +val f_bdHoareF_old : form -> xpath -> form -> hoarecmp -> form -> form +val f_bdHoareS : memtype -> ss_inv -> stmt -> ss_inv -> hoarecmp -> ss_inv -> form +val f_bdHoareS_old : memenv -> form -> stmt -> form -> hoarecmp -> form -> form (* soft-constructors - equiv *) -val f_equivS : memenv -> memenv -> form -> stmt -> stmt -> form -> form -val f_equivF : form -> xpath -> xpath -> form -> form - -val f_equivS_r : equivS -> form -val f_equivF_r : equivF -> form +val f_equivF : ts_inv -> xpath -> xpath -> ts_inv -> form +val f_equivF_old : form -> xpath -> xpath -> form -> form +val f_equivS : memtype -> memtype -> ts_inv -> stmt -> stmt -> ts_inv -> form +val f_equivS_old : memenv -> memenv -> form -> stmt -> stmt -> form -> form (* soft-constructors - eager *) -val f_eagerF_r : eagerF -> form -val f_eagerF : form -> stmt -> xpath -> xpath -> stmt -> form -> form +val f_eagerF : ts_inv -> stmt -> xpath -> xpath -> stmt -> ts_inv -> form +val f_eagerF_old : form -> stmt -> xpath -> xpath -> stmt -> form -> form (* soft-constructors - Pr *) val f_pr_r : pr -> form -val f_pr : memory -> xpath -> form -> form -> form +val f_pr : memory -> xpath -> form -> ss_inv -> form (* soft-constructors - unit *) val f_tt : form @@ -325,12 +318,17 @@ val split_fun : form -> bindings * form val split_args : form -> form * form list (* -------------------------------------------------------------------- *) -val form_of_expr : EcMemory.memory -> EcTypes.expr -> form +val form_of_expr : EcTypes.expr -> form +val ss_inv_of_expr : EcMemory.memory -> EcTypes.expr -> ss_inv (* -------------------------------------------------------------------- *) exception CannotTranslate -val expr_of_form : EcMemory.memory -> form -> EcTypes.expr +val expr_of_ss_inv : ss_inv -> EcTypes.expr +val expr_of_form : form -> EcTypes.expr + +(* -------------------------------------------------------------------- *) +(* A predicate on memory: λ mem. -> pred *) (* -------------------------------------------------------------------- *) (* A predicate on memory: λ mem. -> pred *) diff --git a/src/ecCoreSubst.ml b/src/ecCoreSubst.ml index 7e0253c63..b17e794f0 100644 --- a/src/ecCoreSubst.ml +++ b/src/ecCoreSubst.ml @@ -116,7 +116,7 @@ let bind_mod (s : f_subst) (x : ident) (mp : mpath) (ex : mod_extra) : f_subst = let f_bind_absmod (s : f_subst) (m1 : ident) (m2 : ident) : f_subst = bind_mod s m1 (EcPath.mident m2) - { mex_tglob = tglob m2; mex_glob = (fun m -> f_glob m2 m); } + { mex_tglob = tglob m2; mex_glob = (fun m -> (f_glob m2 m).inv); } (* -------------------------------------------------------------------- *) let f_bind_mod (s : f_subst) (x : ident) (mp : mpath) (norm_mod : memory -> form) : f_subst = @@ -441,96 +441,98 @@ module Fsubst = struct let pv' = pv_subst s pv in let m' = m_subst s m in let ty' = ty_subst s fp.f_ty in - f_pvar pv' ty' m' + (f_pvar pv' ty' m').inv | Fglob (mid, m) -> let m' = m_subst s m in begin match Mid.find_opt mid s.fs_mod with - | None -> f_glob mid m' + | None -> (f_glob mid m').inv | Some _ -> (Mid.find mid s.fs_modex).mex_glob m' end | FhoareF hf -> - let hf_f = x_subst s hf.hf_f in - let s = f_rem_mem s mhr in - let hf_pr = f_subst ~tx s hf.hf_pr in - let hf_po = f_subst ~tx s hf.hf_po in - f_hoareF hf_pr hf_f hf_po + let hf_f = x_subst s hf.hf_f in + let (s, m) = add_m_binding s hf.hf_m in + let hf_pr = f_subst ~tx s (hf_pr hf).inv in + let hf_po = f_subst ~tx s (hf_po hf).inv in + f_hoareF {m;inv=hf_pr} hf_f {m;inv=hf_po} | FhoareS hs -> let hs_s = s_subst s hs.hs_s in - let s, hs_m = add_me_binding s hs.hs_m in - let hs_pr = f_subst ~tx s hs.hs_pr in - let hs_po = f_subst ~tx s hs.hs_po in - f_hoareS hs_m hs_pr hs_s hs_po + let s, (m, mt) = add_me_binding s hs.hs_m in + let hs_pr = f_subst ~tx s (hs_pr hs).inv in + let hs_po = f_subst ~tx s (hs_po hs).inv in + f_hoareS mt {m;inv=hs_pr} hs_s {m;inv=hs_po} | FeHoareF hf -> let hf_f = x_subst s hf.ehf_f in - let s = f_rem_mem s mhr in - let hf_pr = f_subst ~tx s hf.ehf_pr in - let hf_po = f_subst ~tx s hf.ehf_po in - f_eHoareF hf_pr hf_f hf_po + let (s, m) = add_m_binding s hf.ehf_m in + let hf_pr = f_subst ~tx s (ehf_pr hf).inv in + let hf_po = f_subst ~tx s (ehf_po hf).inv in + f_eHoareF {m;inv=hf_pr} hf_f {m;inv=hf_po} | FeHoareS hs -> let hs_s = s_subst s hs.ehs_s in - let s, hs_m = add_me_binding s hs.ehs_m in - let hs_pr = f_subst ~tx s hs.ehs_pr in - let hs_po = f_subst ~tx s hs.ehs_po in - f_eHoareS hs_m hs_pr hs_s hs_po + let s, (m, mt) = add_me_binding s hs.ehs_m in + let hs_pr = f_subst ~tx s (ehs_pr hs).inv in + let hs_po = f_subst ~tx s (ehs_po hs).inv in + f_eHoareS mt {m;inv=hs_pr} hs_s {m;inv=hs_po} | FbdHoareF hf -> let hf_f = x_subst s hf.bhf_f in - let s = f_rem_mem s mhr in - let hf_pr = f_subst ~tx s hf.bhf_pr in - let hf_po = f_subst ~tx s hf.bhf_po in - let hf_bd = f_subst ~tx s hf.bhf_bd in - f_bdHoareF hf_pr hf_f hf_po hf.bhf_cmp hf_bd + let (s, m) = add_m_binding s hf.bhf_m in + let hf_pr = f_subst ~tx s (bhf_pr hf).inv in + let hf_po = f_subst ~tx s (bhf_po hf).inv in + let hf_bd = f_subst ~tx s (bhf_bd hf).inv in + f_bdHoareF {m;inv=hf_pr} hf_f {m;inv=hf_po} hf.bhf_cmp {m;inv=hf_bd} | FbdHoareS hs -> let hs_s = s_subst s hs.bhs_s in let s, hs_m = add_me_binding s hs.bhs_m in - let hs_pr = f_subst ~tx s hs.bhs_pr in - let hs_po = f_subst ~tx s hs.bhs_po in - let hs_bd = f_subst ~tx s hs.bhs_bd in - f_bdHoareS hs_m hs_pr hs_s hs_po hs.bhs_cmp hs_bd + let m = fst hs_m in + let hs_pr = f_subst ~tx s (bhs_pr hs).inv in + let hs_po = f_subst ~tx s (bhs_po hs).inv in + let hs_bd = f_subst ~tx s (bhs_bd hs).inv in + f_bdHoareS (snd hs_m) {m;inv=hs_pr} hs_s {m;inv=hs_po} hs.bhs_cmp {m;inv=hs_bd} | FequivF ef -> let ef_fl = x_subst s ef.ef_fl in let ef_fr = x_subst s ef.ef_fr in - let s = f_rem_mem s mleft in - let s = f_rem_mem s mright in - let ef_pr = f_subst ~tx s ef.ef_pr in - let ef_po = f_subst ~tx s ef.ef_po in - f_equivF ef_pr ef_fl ef_fr ef_po + let (s, ml) = add_m_binding s ef.ef_ml in + let (s, mr) = add_m_binding s ef.ef_mr in + let ef_pr = f_subst ~tx s (ef_pr ef).inv in + let ef_po = f_subst ~tx s (ef_po ef).inv in + f_equivF {ml;mr;inv=ef_pr} ef_fl ef_fr {ml;mr;inv=ef_po} | FequivS es -> let es_sl = s_subst s es.es_sl in let es_sr = s_subst s es.es_sr in - let s, es_ml = add_me_binding s es.es_ml in - let s, es_mr = add_me_binding s es.es_mr in - let es_pr = f_subst ~tx s es.es_pr in - let es_po = f_subst ~tx s es.es_po in - f_equivS es_ml es_mr es_pr es_sl es_sr es_po + let s, (ml, mlt) = add_me_binding s es.es_ml in + let s, (mr, mrt) = add_me_binding s es.es_mr in + let es_pr = f_subst ~tx s (es_pr es).inv in + let es_po = f_subst ~tx s (es_po es).inv in + f_equivS mlt mrt {ml;mr;inv=es_pr} es_sl es_sr {ml;mr;inv=es_po} | FeagerF eg -> let eg_fl = x_subst s eg.eg_fl in let eg_fr = x_subst s eg.eg_fr in let eg_sl = s_subst s eg.eg_sl in let eg_sr = s_subst s eg.eg_sr in - let s = f_rem_mem s mleft in - let s = f_rem_mem s mright in - let eg_pr = f_subst ~tx s eg.eg_pr in - let eg_po = f_subst ~tx s eg.eg_po in - f_eagerF eg_pr eg_sl eg_fl eg_fr eg_sr eg_po + let (s, ml) = add_m_binding s eg.eg_ml in + let (s, mr) = add_m_binding s eg.eg_mr in + let eg_pr = f_subst ~tx s (eg_pr eg).inv in + let eg_po = f_subst ~tx s (eg_po eg).inv in + f_eagerF {ml;mr;inv=eg_pr} eg_sl eg_fl eg_fr eg_sr {ml;mr;inv=eg_po} | Fpr pr -> let pr_mem = m_subst s pr.pr_mem in let pr_fun = x_subst s pr.pr_fun in let pr_args = f_subst ~tx s pr.pr_args in - let s = f_rem_mem s mhr in - let pr_event = f_subst ~tx s pr.pr_event in + let ev = pr.pr_event in + let (s, m) = add_m_binding s ev.m in + let pr_event = f_subst ~tx s ev.inv in - f_pr pr_mem pr_fun pr_args pr_event + f_pr pr_mem pr_fun pr_args {m;inv=pr_event} | _ -> f_map (ty_subst s) (f_subst ~tx s) fp) @@ -615,6 +617,16 @@ module Fsubst = struct s, params (* ------------------------------------------------------------------ *) + and add_m_binding (s : f_subst) (m : memory) : f_subst * memory = + let m' = refresh s m in + if m == m' then + let s = f_rem_mem s m in + (s, m) + else + let s = f_bind_mem s m m' in + (s, m') + (* ------------------------------------------------------------------ *) + and add_me_binding (s : f_subst) ((x, mt) as me : memenv) : f_subst * memenv = let mt' = EcMemory.mt_subst (ty_subst s) mt in let x' = refresh s x in diff --git a/src/ecEnv.ml b/src/ecEnv.ml index b6ba72eda..838859a91 100644 --- a/src/ecEnv.ml +++ b/src/ecEnv.ml @@ -176,7 +176,8 @@ type preenv = { env_comps : mc Mip.t; env_locals : (EcIdent.t * EcTypes.ty) MMsym.t; env_memories : EcMemory.memtype Mmem.t; - env_actmem : EcMemory.memory option; + env_actmem_ss: EcMemory.memory option; + env_actmem_ts: (EcMemory.memory * EcMemory.memory) option; env_abs_st : EcModules.abs_uses Mid.t; env_tci : ((ty_params * ty) * tcinstance) list; env_tc : TC.graph; @@ -305,7 +306,8 @@ let empty gstate = env_comps = Mip.singleton (IPPath path) (empty_mc None); env_locals = MMsym.empty; env_memories = Mmem.empty; - env_actmem = None; + env_actmem_ss= None; + env_actmem_ts= None; env_abs_st = Mid.empty; env_tci = []; env_tc = TC.Graph.empty; @@ -1258,18 +1260,36 @@ module Memory = struct try Some (Mmem.bysym me env.env_memories) with Not_found -> None - let set_active (me : memory) (env : env) = + let set_active_ss (me : memory) (env : env) = match byid me env with | None -> raise (MEError (UnknownMemory (`Memory me))) - | Some _ -> { env with env_actmem = Some me } + | Some _ -> { env with env_actmem_ss = Some me } - let get_active (env : env) = - env.env_actmem + let get_active_ss (env : env) = + env.env_actmem_ss - let current (env : env) = - match env.env_actmem with + let current_ss (env : env) = + match env.env_actmem_ss with | None -> None | Some me -> byid me env + + let set_active_ts (ml: memory) (mr: memory) (env : env) = + match byid ml env, byid mr env with + | None, _ -> raise (MEError (UnknownMemory (`Memory ml))) + | _, None -> raise (MEError (UnknownMemory (`Memory mr))) + | Some _, Some _ -> + { env with env_actmem_ts = Some (ml, mr) } + + let get_active_ts (env : env) = + env.env_actmem_ts + + let current_ts (env : env) = + match env.env_actmem_ts with + | None -> None + | Some (ml, mr) -> + match byid ml env, byid mr env with + | Some mel, Some mer -> Some (mel, mer) + | _ -> None let update (me: EcMemory.memenv) (env : env) = { env with env_memories = Mmem.add (fst me) (snd me) env.env_memories; } @@ -1284,10 +1304,14 @@ module Memory = struct (fun env m -> push m env) env memenvs - let push_active memenv env = - set_active (EcMemory.memory memenv) + let push_active_ss memenv env = + set_active_ss (EcMemory.memory memenv) (push memenv env) + let push_active_ts mel mer env = + set_active_ts (EcMemory.memory mel) (EcMemory.memory mer) + (push mer (push mel env)) + end (* -------------------------------------------------------------------- *) @@ -1685,60 +1709,61 @@ module Fun = struct let id = if side = `Left then EcCoreFol.mleft else EcCoreFol.mright in EcMemory.abstract id - let inv_memenv env = - Memory.push_all [inv_memory `Left; inv_memory `Rigth] env + let inv_memenv ml mr env = + Memory.push_active_ts (EcMemory.abstract ml) (EcMemory.abstract mr) env - let inv_memenv1 env = - let mem = EcMemory.abstract EcCoreFol.mhr in - Memory.push_active mem env + let inv_memenv1 m env = + let mem = EcMemory.abstract m in + Memory.push_active_ss mem env let prF_memenv m path env = let fun_ = by_xpath path env in actmem_post m fun_ - let prF path env = - let post = prF_memenv EcCoreFol.mhr path env in - Memory.push_active post env + let prF m path env = + let post = prF_memenv m path env in + Memory.push_active_ss post env - let hoareF_memenv path env = + (* FIXME: This does not use the memory identifier except to return it *) + let hoareF_memenv mem path env = let (ip, _) = oget (ipath_of_xpath path) in let fun_ = snd (oget (by_ipath ip env)) in - let pre = actmem_pre EcCoreFol.mhr fun_ in - let post = actmem_post EcCoreFol.mhr fun_ in + let pre = actmem_pre mem fun_ in + let post = actmem_post mem fun_ in pre, post - let hoareF path env = - let pre, post = hoareF_memenv path env in - Memory.push_active pre env, Memory.push_active post env + let hoareF mem path env = + let pre, post = hoareF_memenv mem path env in + Memory.push_active_ss pre env, Memory.push_active_ss post env - let hoareS path env = + let hoareS mem path env = let fun_ = by_xpath path env in - let fd, memenv = actmem_body EcCoreFol.mhr fun_ in - memenv, fd, Memory.push_active memenv env + let fd, memenv = actmem_body mem fun_ in + memenv, fd, Memory.push_active_ss memenv env - let equivF_memenv path1 path2 env = + let equivF_memenv ml mr path1 path2 env = let (ip1, _) = oget (ipath_of_xpath path1) in let (ip2, _) = oget (ipath_of_xpath path2) in let fun1 = snd (oget (by_ipath ip1 env)) in let fun2 = snd (oget (by_ipath ip2 env)) in - let pre1 = actmem_pre EcCoreFol.mleft fun1 in - let pre2 = actmem_pre EcCoreFol.mright fun2 in - let post1 = actmem_post EcCoreFol.mleft fun1 in - let post2 = actmem_post EcCoreFol.mright fun2 in + let pre1 = actmem_pre ml fun1 in + let pre2 = actmem_pre mr fun2 in + let post1 = actmem_post ml fun1 in + let post2 = actmem_post mr fun2 in (pre1,pre2), (post1,post2) - let equivF path1 path2 env = - let (pre1,pre2),(post1,post2) = equivF_memenv path1 path2 env in - Memory.push_all [pre1; pre2] env, - Memory.push_all [post1; post2] env + let equivF ml mr path1 path2 env = + let (prel,prer),(postl,postr) = equivF_memenv ml mr path1 path2 env in + Memory.push_active_ts prel prer env, + Memory.push_active_ts postl postr env - let equivS path1 path2 env = + let equivS ml mr path1 path2 env = let fun1 = by_xpath path1 env in let fun2 = by_xpath path2 env in - let fd1, mem1 = actmem_body EcCoreFol.mleft fun1 in - let fd2, mem2 = actmem_body EcCoreFol.mright fun2 in - mem1, fd1, mem2, fd2, Memory.push_all [mem1; mem2] env + let fd1, mem1 = actmem_body ml fun1 in + let fd2, mem2 = actmem_body mr fun2 in + mem1, fd1, mem2, fd2, Memory.push_active_ts mem1 mem2 env end (* -------------------------------------------------------------------- *) @@ -2448,13 +2473,13 @@ module NormMp = struct let globs = List.map (fun id -> f_glob id m) globs in let pv = List.map (fun (xp, ty) -> f_pvar (pv_glob xp) ty m) pv in - f_tuple (globs @ pv) + map_ss_inv ~m f_tuple (globs @ pv) let norm_glob env m mp = globals env m mp let norm_tglob env mp = - let g = (norm_glob env mhr mp) in - g.f_ty + let g = (norm_glob env (EcIdent.create "&dummy_shouldnotleak") mp) in + g.inv.f_ty let is_abstract_fun f env = let f = norm_xfun env f in @@ -3588,26 +3613,29 @@ module LDecl = struct let fresh_ids hyps s = snd (fresh_ids (tohyps hyps) s) (* ------------------------------------------------------------------ *) - let push_active m lenv = - { lenv with le_env = Memory.push_active m lenv.le_env } + let push_active_ss m lenv = + { lenv with le_env = Memory.push_active_ss m lenv.le_env } + + let push_active_ts ml mr lenv = + { lenv with le_env = Memory.push_active_ts ml mr lenv.le_env } let push_all l lenv = { lenv with le_env = Memory.push_all l lenv.le_env } - let hoareF xp lenv = - let env1, env2 = Fun.hoareF xp lenv.le_env in + let hoareF mem xp lenv = + let env1, env2 = Fun.hoareF mem xp lenv.le_env in { lenv with le_env = env1}, {lenv with le_env = env2 } - let equivF xp1 xp2 lenv = - let env1, env2 = Fun.equivF xp1 xp2 lenv.le_env in + let equivF ml mr xp1 xp2 lenv = + let env1, env2 = Fun.equivF ml mr xp1 xp2 lenv.le_env in { lenv with le_env = env1}, {lenv with le_env = env2 } - let inv_memenv lenv = - { lenv with le_env = Fun.inv_memenv lenv.le_env } + let inv_memenv ml mr lenv = + { lenv with le_env = Fun.inv_memenv ml mr lenv.le_env } - let inv_memenv1 lenv = - { lenv with le_env = Fun.inv_memenv1 lenv.le_env } + let inv_memenv1 m lenv = + { lenv with le_env = Fun.inv_memenv1 m lenv.le_env } end -let pp_debug_form = ref (fun _env _fmt _f -> assert false) +let pp_debug_form = ref (fun _env _f -> assert false) diff --git a/src/ecEnv.mli b/src/ecEnv.mli index 4743bc9d0..cfbdad642 100644 --- a/src/ecEnv.mli +++ b/src/ecEnv.mli @@ -64,16 +64,20 @@ type meerror = exception MEError of meerror module Memory : sig - val all : env -> memenv list - val set_active : memory -> env -> env - val get_active : env -> memory option - - val byid : memory -> env -> memenv option - val lookup : symbol -> env -> memenv option - val current : env -> memenv option - val push : memenv -> env -> env - val push_all : memenv list -> env -> env - val push_active : memenv -> env -> env + val all : env -> memenv list + val set_active_ss : memory -> env -> env + val get_active_ss : env -> memory option + val set_active_ts : memory -> memory -> env -> env + val get_active_ts : env -> (memory * memory) option + + val byid : memory -> env -> memenv option + val lookup : symbol -> env -> memenv option + val current_ss : env -> memenv option + val current_ts : env -> (memenv * memenv) option + val push : memenv -> env -> env + val push_all : memenv list -> env -> env + val push_active_ss: memenv -> env -> env + val push_active_ts: memenv -> memenv -> env -> env end (* -------------------------------------------------------------------- *) @@ -93,29 +97,29 @@ module Fun : sig val add : xpath -> env -> env (* ------------------------------------------------------------------ *) - val prF_memenv : EcMemory.memory -> xpath -> env -> memenv + val prF_memenv : memory -> xpath -> env -> memenv - val prF : xpath -> env -> env + val prF : memory -> xpath -> env -> env - val hoareF_memenv : xpath -> env -> memenv * memenv + val hoareF_memenv : memory -> xpath -> env -> memenv * memenv - val hoareF : xpath -> env -> env * env + val hoareF : memory -> xpath -> env -> env * env - val hoareS : xpath -> env -> memenv * (funsig * function_def) * env + val hoareS : memory -> xpath -> env -> memenv * (funsig * function_def) * env val actmem_body : memory -> function_ -> (funsig * function_def) * memenv val actmem_post : memory -> function_ -> memenv val inv_memory : [`Left|`Right] -> memenv - val inv_memenv : env -> env + val inv_memenv : memory -> memory -> env -> env - val equivF_memenv : xpath -> xpath -> env -> + val equivF_memenv : memory -> memory -> xpath -> xpath -> env -> (memenv * memenv) * (memenv * memenv) - val equivF : xpath -> xpath -> env -> env * env + val equivF : memory -> memory -> xpath -> xpath -> env -> env * env - val equivS : xpath -> xpath -> env -> + val equivS : memory -> memory -> xpath -> xpath -> env -> memenv * (funsig * function_def) * memenv * (funsig * function_def) * env end @@ -246,7 +250,7 @@ module NormMp : sig val flatten_use : use -> EcIdent.t list * (xpath * ty) list - val norm_glob : env -> EcMemory.memory -> mpath -> form + val norm_glob : env -> EcMemory.memory -> mpath -> ss_inv val norm_tglob : env -> mpath -> EcTypes.ty val is_abstract_fun : xpath -> env -> bool @@ -502,14 +506,15 @@ module LDecl : sig val clear : ?leniant:bool -> EcIdent.Sid.t -> hyps -> hyps - val push_all : memenv list -> hyps -> hyps - val push_active : memenv -> hyps -> hyps + val push_all : memenv list -> hyps -> hyps + val push_active_ss : memenv -> hyps -> hyps + val push_active_ts : memenv -> memenv -> hyps -> hyps - val hoareF : xpath -> hyps -> hyps * hyps - val equivF : xpath -> xpath -> hyps -> hyps * hyps + val hoareF : memory -> xpath -> hyps -> hyps * hyps + val equivF : memory -> memory -> xpath -> xpath -> hyps -> hyps * hyps - val inv_memenv : hyps -> hyps - val inv_memenv1 : hyps -> hyps + val inv_memenv : memory -> memory -> hyps -> hyps + val inv_memenv1 : memory ->hyps -> hyps end -val pp_debug_form : (env -> Format.formatter -> form -> unit) ref +val pp_debug_form : (env -> form -> unit) ref diff --git a/src/ecFol.ml b/src/ecFol.ml index b1f839a6f..638f6a0a1 100644 --- a/src/ecFol.ml +++ b/src/ecFol.ml @@ -15,16 +15,16 @@ include EcCoreSubst (* -------------------------------------------------------------------- *) let f_bind_mod s x mp env = - Fsubst.f_bind_mod s x mp (fun mem -> EcEnv.NormMp.norm_glob env mem mp) + Fsubst.f_bind_mod s x mp (fun mem -> (EcEnv.NormMp.norm_glob env mem mp).inv) (* -------------------------------------------------------------------- *) let f_eqparams ty1 vs1 m1 ty2 vs2 m2 = let f_pvlocs ty vs m = let arg = f_pvarg ty m in - if List.length vs = 1 then [arg] + if List.length vs = 1 then [arg.inv] else let t = Array.of_list vs in - let t = Array.mapi (fun i vd -> f_proj arg i vd.ov_type) t in + let t = Array.mapi (fun i vd -> f_proj arg.inv i vd.ov_type) t in Array.to_list t in @@ -33,13 +33,25 @@ let f_eqparams ty1 vs1 m1 ty2 vs2 m2 = else f_eq (f_tuple (f_pvlocs ty1 vs1 m1)) (f_tuple (f_pvlocs ty2 vs2 m2)) -let f_eqres ty1 m1 ty2 m2 = - f_eq (f_pvar pv_res ty1 m1) (f_pvar pv_res ty2 m2) +let ts_inv_eqparams ty1 vs1 ml ty2 vs2 mr = + let inv = f_eqparams ty1 vs1 ml ty2 vs2 mr in + {inv; ml; mr} + +let f_eqres ty1 m1 ty2 m2 = (* TODO: deprecate in favor of `ts_inv_eqres` *) + f_eq (f_pvar pv_res ty1 m1).inv (f_pvar pv_res ty2 m2).inv + +let ts_inv_eqres ty1 ml ty2 mr = + let inv = f_eqres ty1 ml ty2 mr in + {inv; ml; mr} let f_eqglob mp1 m1 mp2 m2 = let mp1 = EcPath.mget_ident mp1 in let mp2 = EcPath.mget_ident mp2 in - f_eq (f_glob mp1 m1) (f_glob mp2 m2) + f_eq (f_glob mp1 m1).inv (f_glob mp2 m2).inv + +let ts_inv_eqglob mp1 ml mp2 mr = + let inv = f_eqglob mp1 ml mp2 mr in + {inv; ml; mr} (* -------------------------------------------------------------------- *) let f_op_real_of_int = (* CORELIB *) @@ -216,7 +228,7 @@ let f_dlet tya tyb d f = f_app (fop_dlet tya tyb) [d; f] (tdistr tyb) (* -------------------------------------------------------------------- *) -let f_losslessF f = f_bdHoareF f_true f f_true FHeq f_r1 +let f_losslessF f = f_bdHoareF {m=mhr;inv=f_true} f {m=mhr;inv=f_true} FHeq {m=mhr;inv=f_r1} (* -------------------------------------------------------------------- *) let f_identity ?(name = "x") ty = @@ -1060,20 +1072,19 @@ let rec one_sided mem fp = | _ -> false let rec split_sided mem fp = - if one_sided mem fp then - Some fp + if one_sided mem fp.inv then + Some {m=mem;inv=fp.inv} else - if is_and fp then - let (l, r) = destr_and fp in + if is_and fp.inv then + let (l, r) = map_ts_inv_destr2 destr_and fp in let fl = split_sided mem l in let fr = split_sided mem r in - if is_none fr then - fl - else - (match fl with - | Some f -> Some (f_and f (oget fr)) - | None -> fr - ) + match fl, fr with + | None, None -> None + | Some f, None -> Some f + | None, Some f -> Some f + | Some fl, Some fr -> + Some (map_ss_inv2 f_and fl fr) else None @@ -1114,7 +1125,7 @@ let rec dump_f f = | Fapp (f, a) -> "APP " ^ dump_f f ^ " ( " ^ String.concat ", " (List.map dump_f a) ^ " )" | Ftuple f -> " ( " ^ String.concat ", " (List.map dump_f f) ^ " )" | Fproj (f, x) -> dump_f f ^ "." ^ string_of_int x - | Fpr {pr_args = a; pr_event = e} -> "PR [ARG = " ^ dump_f a ^ " ; EV = " ^ dump_f e ^ "]" + | Fpr {pr_args = a; pr_event = e} -> "PR [ARG = " ^ dump_f a ^ " ; EV = " ^ dump_f e.inv ^ "]" | FhoareF _ -> "HoareF" | FhoareS _ -> "HoareS" | FbdHoareF _ -> "bdHoareF" diff --git a/src/ecFol.mli b/src/ecFol.mli index 403224fe8..108bed966 100644 --- a/src/ecFol.mli +++ b/src/ecFol.mli @@ -1,8 +1,7 @@ (* -------------------------------------------------------------------- *) open EcBigInt open EcPath -open EcTypes -open EcMemory +open EcAst (* -------------------------------------------------------------------- *) include module type of struct include EcCoreFol end @@ -20,16 +19,31 @@ val f_eqparams: -> EcTypes.ty -> ovariable list -> memory -> form +val ts_inv_eqparams: + EcTypes.ty -> ovariable list -> memory + -> EcTypes.ty -> ovariable list -> memory + -> ts_inv + val f_eqres: EcTypes.ty -> memory -> EcTypes.ty -> memory -> form +val ts_inv_eqres: + EcTypes.ty -> memory + -> EcTypes.ty -> memory + -> ts_inv + val f_eqglob: mpath -> memory -> mpath -> memory -> form +val ts_inv_eqglob: + mpath -> memory + -> mpath -> memory + -> ts_inv + (* soft-constructors - ordering *) val f_int_le : form -> form -> form val f_int_lt : form -> form -> form @@ -93,7 +107,7 @@ val f_dmap : ty -> ty -> form -> form -> form (* common functions *) val f_identity : ?name:EcSymbols.symbol -> EcTypes.ty -> form -val split_sided : memory -> form -> form option +val split_sided : memory -> ts_inv -> ss_inv option val one_sided_vs : memory -> form -> form list (* -------------------------------------------------------------------- *) diff --git a/src/ecHiGoal.ml b/src/ecHiGoal.ml index dc1a6b8e1..f08413545 100644 --- a/src/ecHiGoal.ml +++ b/src/ecHiGoal.ml @@ -1725,8 +1725,8 @@ let process_generalize1 ?(doeq = false) pattern (tc : tcenv1) = let newconcl = concl |> FPosition.map ptnpos (fun f -> match f.f_node with - | Fglob (a, _) -> f_glob a m' - | Fpvar (p, _) -> f_pvar p f.f_ty m' + | Fglob (a, _) -> (f_glob a m').inv + | Fpvar (p, _) -> (f_pvar p f.f_ty m').inv | Fpr pr -> f_pr_r { pr with pr_mem = m' } | _ -> assert false ) in diff --git a/src/ecHiTacticals.ml b/src/ecHiTacticals.ml index 1973bef55..30e0a7355 100644 --- a/src/ecHiTacticals.ml +++ b/src/ecHiTacticals.ml @@ -6,6 +6,7 @@ open EcParsetree open EcCoreGoal open EcCoreGoal.FApi open EcHiGoal +open EcAst module TTC = EcProofTyping @@ -81,7 +82,7 @@ and process1_case (_ : ttenv) (doeq, opts, gp) (tc : tcenv1) = match (FApi.tc1_goal tc).f_node with | FbdHoareS _ | FhoareS _ | FeHoareS _ when not opts.cod_ambient -> let _, fp = TTC.tc1_process_Xhl_formula tc (form_of_gp ()) in - EcPhlCase.t_hl_case fp tc + EcPhlCase.t_hl_case (Inv_ss fp) tc | FequivS _ when not opts.cod_ambient -> let fp = TTC.tc1_process_prhl_formula tc (form_of_gp ()) in diff --git a/src/ecLowGoal.ml b/src/ecLowGoal.ml index 6643c8e3c..fd20b27fd 100644 --- a/src/ecLowGoal.ml +++ b/src/ecLowGoal.ml @@ -15,12 +15,42 @@ open EcCoreGoal open EcBaseLogic open EcProofTerm + module EP = EcParsetree module ER = EcReduction module TTC = EcProofTyping module LG = EcCoreLib.CI_Logic module PT = EcProofTerm +(* -------------------------------------------------------------------- *) + +let pp_tc tc = + let pr = proofenv_of_proof (proof_of_tcenv tc) in + let cl = List.map (FApi.get_pregoal_by_id^~ pr) (FApi.tc_opened tc) in + let cl = List.map (fun x -> (EcEnv.LDecl.tohyps x.g_hyps, x.g_concl)) cl in + + match cl with [] -> () | hd :: tl -> + + Format.eprintf "%a@." + (EcPrinting.pp_goal (EcPrinting.PPEnv.ofenv (FApi.tc_env tc)) {prpo_pr = true; prpo_po = true}) + (hd, `All tl) + +type cstate = { + cs_undosubst : Sid.t; + cs_sbeq : Sid.t; +} + +let pp_tc1 tc = + pp_tc (FApi.tcenv_of_tcenv1 tc) + +let t_debug ?(tag="") t tc = + Format.eprintf "Before (tag: %s):" tag; + pp_tc (FApi.tcenv_of_tcenv1 tc); + let r = t tc in + Format.eprintf "After (tag: %s):" tag; + pp_tc r; + r + (* -------------------------------------------------------------------- *) let (@!) (t1 : FApi.backward) (t2 : FApi.backward) = FApi.t_seq t1 t2 @@ -811,6 +841,7 @@ module Apply = struct try t_apply_bwd ?ri ?mode ?canview pt tc with (NoInstance (_, r, pt, f)) -> tc_error_exn !!tc (NoInstance (dpe, r, pt, f)) + end (* -------------------------------------------------------------------- *) @@ -947,7 +978,7 @@ let alpha_find_in_hyps hyps f = LowAssumption.gen_find_in_hyps (EcReduction.is_alpha_eq hyps f) hyps let t_assumption mode (tc : tcenv1) = - let convs = + let (convs: (LDecl.hyps -> _) list) = match mode with | `Alpha -> [EcReduction.is_alpha_eq] | `Conv -> [EcReduction.is_alpha_eq; EcReduction.is_conv] @@ -2272,24 +2303,6 @@ let t_progress ?options ?ti (tt : FApi.backward) (tc : tcenv1) = in entry tc -(* -------------------------------------------------------------------- *) - -let pp_tc tc = - let pr = proofenv_of_proof (proof_of_tcenv tc) in - let cl = List.map (FApi.get_pregoal_by_id^~ pr) (FApi.tc_opened tc) in - let cl = List.map (fun x -> (EcEnv.LDecl.tohyps x.g_hyps, x.g_concl)) cl in - - match cl with [] -> () | hd :: tl -> - - Format.eprintf "%a@." - (EcPrinting.pp_goal (EcPrinting.PPEnv.ofenv (FApi.tc_env tc)) {prpo_pr = true; prpo_po = true}) - (hd, `All tl) - -type cstate = { - cs_undosubst : Sid.t; - cs_sbeq : Sid.t; -} - let t_crush ?(delta = true) ?tsolve (tc : tcenv1) = let dtsolve = @@ -2299,11 +2312,6 @@ let t_crush ?(delta = true) ?tsolve (tc : tcenv1) = let tt = FApi.t_try (t_assumption `Alpha) in -(* let t_print s t tc = - Format.eprintf "%s@." s; - pp_tc (FApi.tcenv_of_tcenv1 tc); - t tc in *) - (* Entry of progress: simplify goal, and chain with progress *) let rec entry (st : cstate) = t_simplify ~delta:`No @! aux0 st diff --git a/src/ecLowGoal.mli b/src/ecLowGoal.mli index 2f03d513e..56004018a 100644 --- a/src/ecLowGoal.mli +++ b/src/ecLowGoal.mli @@ -351,3 +351,15 @@ val t_solve : -> ?mode:EcMatching.fmoptions -> ?depth:int -> FApi.backward + +val t_debug : + ?tag:string (* for distinguishing prints *) + -> FApi.backward + -> FApi.backward + [@@ocaml.alert debug "Debug function, remove uses before merging"] + +val pp_tc :tcenv -> unit + [@@ocaml.alert debug "Debug function, remove uses before merging"] + +val pp_tc1 :tcenv1 -> unit + [@@ocaml.alert debug "Debug function, remove uses before merging"] \ No newline at end of file diff --git a/src/ecLowPhlGoal.ml b/src/ecLowPhlGoal.ml index 79244af03..e5d081724 100644 --- a/src/ecLowPhlGoal.ml +++ b/src/ecLowPhlGoal.ml @@ -10,6 +10,7 @@ open EcEnv open EcPV open EcCoreGoal open EcMatching.Position +open EcSubst module Zpr = EcMatching.Zipper @@ -208,24 +209,24 @@ let tc1_get_stmt side tc = (* -------------------------------------------------------------------- *) let hl_set_stmt (side : side option) (f : form) (s : stmt) = match side, f.f_node with - | None , FhoareS hs -> f_hoareS_r { hs with hs_s = s } - | None , FeHoareS hs -> f_eHoareS_r { hs with ehs_s = s } - | None , FbdHoareS hs -> f_bdHoareS_r { hs with bhs_s = s } - | Some `Left , FequivS es -> f_equivS_r { es with es_sl = s } - | Some `Right, FequivS es -> f_equivS_r { es with es_sr = s } + | None , FhoareS hs -> f_hoareS (snd hs.hs_m) (hs_pr hs) s (hs_po hs) + | None , FeHoareS hs -> f_eHoareS (snd hs.ehs_m) (ehs_pr hs) s (ehs_po hs) + | None , FbdHoareS hs -> f_bdHoareS (snd hs.bhs_m) (bhs_pr hs) s (bhs_po hs) hs.bhs_cmp (bhs_bd hs) + | Some `Left , FequivS es -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) s es.es_sr (es_po es) + | Some `Right, FequivS es -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) es.es_sl s (es_po es) | _ , _ -> assert false (* -------------------------------------------------------------------- *) let get_pre f = match f.f_node with - | FhoareF hf -> Some (hf.hf_pr ) - | FhoareS hs -> Some (hs.hs_pr ) - | FeHoareF hf -> Some (hf.ehf_pr) - | FeHoareS hs -> Some (hs.ehs_pr) - | FbdHoareF hf -> Some (hf.bhf_pr) - | FbdHoareS hs -> Some (hs.bhs_pr) - | FequivF ef -> Some (ef.ef_pr ) - | FequivS es -> Some (es.es_pr ) + | FhoareF hf -> Some (Inv_ss (hf_pr hf)) + | FhoareS hs -> Some (Inv_ss (hs_pr hs)) + | FeHoareF hf -> Some (Inv_ss (ehf_pr hf)) + | FeHoareS hs -> Some (Inv_ss (ehs_pr hs)) + | FbdHoareF hf -> Some (Inv_ss (bhf_pr hf)) + | FbdHoareS hs -> Some (Inv_ss (bhs_pr hs)) + | FequivF ef -> Some (Inv_ts (ef_pr ef)) + | FequivS es -> Some (Inv_ts (es_pr es)) | _ -> None let tc1_get_pre tc = @@ -236,16 +237,17 @@ let tc1_get_pre tc = (* -------------------------------------------------------------------- *) let get_post f = match f.f_node with - | FhoareF hf -> Some (hf.hf_po ) - | FhoareS hs -> Some (hs.hs_po ) - | FeHoareF hf -> Some (hf.ehf_po) - | FeHoareS hs -> Some (hs.ehs_po) - | FbdHoareF hf -> Some (hf.bhf_po) - | FbdHoareS hs -> Some (hs.bhs_po) - | FequivF ef -> Some (ef.ef_po ) - | FequivS es -> Some (es.es_po ) + | FhoareF hf -> Some (Inv_ss (hf_po hf)) + | FhoareS hs -> Some (Inv_ss (hs_po hs)) + | FeHoareF hf -> Some (Inv_ss (ehf_po hf)) + | FeHoareS hs -> Some (Inv_ss (ehs_po hs)) + | FbdHoareF hf -> Some (Inv_ss (bhf_po hf)) + | FbdHoareS hs -> Some (Inv_ss (bhs_po hs)) + | FequivF ef -> Some (Inv_ts (ef_po ef)) + | FequivS es -> Some (Inv_ts (es_po es)) | _ -> None + let tc1_get_post tc = match get_post (FApi.tc1_goal tc) with | None -> tc_error_noXhl ~kinds:hlkinds_Xhl !!tc @@ -253,15 +255,31 @@ let tc1_get_post tc = (* -------------------------------------------------------------------- *) let set_pre ~pre f = - match f.f_node with - | FhoareF hf -> f_hoareF pre hf.hf_f hf.hf_po - | FhoareS hs -> f_hoareS_r { hs with hs_pr = pre } - | FeHoareF hf -> f_eHoareF_r { hf with ehf_pr = pre } - | FeHoareS hs -> f_eHoareS_r { hs with ehs_pr = pre } - | FbdHoareF hf -> f_bdHoareF pre hf.bhf_f hf.bhf_po hf.bhf_cmp hf.bhf_bd - | FbdHoareS hs -> f_bdHoareS_r { hs with bhs_pr = pre } - | FequivF ef -> f_equivF pre ef.ef_fl ef.ef_fr ef.ef_po - | FequivS es -> f_equivS_r { es with es_pr = pre } + match f.f_node, pre with + | FhoareF hf, Inv_ss pre -> + let pre = ss_inv_rebind pre hf.hf_m in + f_hoareF pre hf.hf_f (hf_po hf) + | FhoareS hs, Inv_ss pre -> + let pre = ss_inv_rebind pre (fst hs.hs_m) in + f_hoareS (snd hs.hs_m) pre hs.hs_s (hs_po hs) + | FeHoareF hf, Inv_ss pre -> + let pre = ss_inv_rebind pre hf.ehf_m in + f_eHoareF pre hf.ehf_f (ehf_po hf) + | FeHoareS hs, Inv_ss pre -> + let pre = ss_inv_rebind pre (fst hs.ehs_m) in + f_eHoareS (snd hs.ehs_m) pre hs.ehs_s (ehs_po hs) + | FbdHoareF hf, Inv_ss pre -> + let pre = ss_inv_rebind pre hf.bhf_m in + f_bdHoareF pre hf.bhf_f (bhf_po hf) hf.bhf_cmp (bhf_bd hf) + | FbdHoareS hs, Inv_ss pre -> + let pre = ss_inv_rebind pre (fst hs.bhs_m) in + f_bdHoareS (snd hs.bhs_m) pre hs.bhs_s (bhs_po hs) hs.bhs_cmp (bhs_bd hs) + | FequivF ef, Inv_ts pre -> + let pre = ts_inv_rebind pre ef.ef_ml ef.ef_mr in + f_equivF pre ef.ef_fl ef.ef_fr (ef_po ef) + | FequivS es, Inv_ts pre -> + let pre = ts_inv_rebind pre (fst es.es_ml) (fst es.es_mr) in + f_equivS (snd es.es_ml) (snd es.es_mr) pre es.es_sl es.es_sr (es_po es) | _ -> assert false (* -------------------------------------------------------------------- *) @@ -448,9 +466,25 @@ let mk_let_of_lv_substs ?(uselet=true) env letsf = else mk_let_of_lv_substs_nolet env letsf (* -------------------------------------------------------------------- *) -let subst_form_lv env m lv t f = - let lets = lv_subst m lv t in - mk_let_of_lv_substs env ([lets], f) +let subst_form_lv env lv t f = + let m = f.m in + assert (f.m = t.m); + let lets = lv_subst f.m lv t.inv in + {m; inv = mk_let_of_lv_substs env ([lets], f.inv)} + +let subst_form_lv_left env lv t f = + let ml, mr = f.ml, f.mr in + assert (f.ml = t.ml); + assert (f.mr = t.mr); + let lets = lv_subst f.ml lv t.inv in + {ml;mr;inv=mk_let_of_lv_substs env ([lets], f.inv)} + +let subst_form_lv_right env lv t f = + let ml, mr = f.ml, f.mr in + assert (f.mr = t.mr); + assert (f.ml = t.ml); + let lets = lv_subst f.mr lv t.inv in + {ml;mr;inv=mk_let_of_lv_substs env ([lets], f.inv)} (* -------------------------------------------------------------------- *) (* Remark: m is only used to create fresh name, id_of_pv *) @@ -473,7 +507,7 @@ let generalize_subst_ env m uelts uglob = in (b', b, s) -let generalize_mod_ env m modi f = +let generalize_mod__ env modi m f = let (melts, mglob) = PV.ntr_elements modi in (* 1. Compute the prog-vars and the globals used in [f] *) @@ -512,16 +546,44 @@ let generalize_mod_ env m modi f = (* 3.c. Perform the substitution *) let s = PVM.of_mpv s m in let f = PVM.subst env s f in - f_forall_simpl (bd'@bd) f, (bd', uglob), (bd, uelts) + {inv=f_forall_simpl (bd'@bd) f; m}, (bd', uglob), (bd, uelts) let generalize_subst env m uelts uglob = let (b',b,f) = generalize_subst_ env m uelts uglob in b'@b, f -let generalize_mod env m modi f = - let res, _, _ = generalize_mod_ env m modi f in +let generalize_mod_ env modi f = + generalize_mod__ env modi f.m f.inv + +let generalize_mod_left_ env modi f = + let ml, mr = f.ml, f.mr in + let res, bd', bd = + generalize_mod__ env modi ml f.inv in + ({ml; mr; inv=res.inv}, bd', bd) + +let generalize_mod_right_ env modi f = + let ml, mr = f.ml, f.mr in + let res, bd', bd = + generalize_mod__ env modi mr f.inv in + ({ml; mr; inv=res.inv}, bd', bd) + +let generalize_mod_ss_inv env modi f = + let res, _, _ = generalize_mod_ env modi f in res +let generalize_mod_left env modi f = + let res, _, _ = generalize_mod_left_ env modi f in + res + +let generalize_mod_right env modi f = + let res, _, _ = generalize_mod_right_ env modi f in + res + +let generalize_mod_ts_inv env modil modir f = + let res = generalize_mod_right env modir f in + generalize_mod_left env modil res + + (* -------------------------------------------------------------------- *) let abstract_info env f1 = let f = EcEnv.NormMp.norm_xfun env f1 in @@ -597,18 +659,19 @@ let t_code_transform (side : oside) ?(bdhoare = false) cpos tr tx tc = let (hyps, concl) = FApi.tc1_flat tc in match concl.f_node with - | FhoareS hoare -> - let pr, po = hoare.hs_pr, hoare.hs_po in + | FhoareS hs -> + let pr, po = hs.hs_pr, hs.hs_po in let (me, stmt, cs) = - tx (pf, hyps) cpos (pr, po) (hoare.hs_m, hoare.hs_s) in - let concl = f_hoareS_r { hoare with hs_m = me; hs_s = stmt; } in + tx (pf, hyps) cpos (pr, po) (hs.hs_m, hs.hs_s) in + let concl = f_hoareS (snd me) (hs_pr hs) stmt (hs_po hs) in FApi.xmutate1 tc (tr None) (cs @ [concl]) | FbdHoareS bhs when bdhoare -> let pr, po = bhs.bhs_pr, bhs.bhs_po in let (me, stmt, cs) = tx (pf, hyps) cpos (pr, po) (bhs.bhs_m, bhs.bhs_s) in - let concl = f_bdHoareS_r { bhs with bhs_m = me; bhs_s = stmt; } in + let concl = f_bdHoareS (snd me) (bhs_pr bhs) stmt (bhs_po bhs) + bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc (tr None) (cs @ [concl]) | _ -> @@ -627,11 +690,11 @@ let t_code_transform (side : oside) ?(bdhoare = false) cpos tr tx tc = match side with | `Left -> (es.es_ml, es.es_sl) | `Right -> (es.es_mr, es.es_sr) in - let me, stmt, cs = tx (pf, hyps) cpos (pre, post) (me, stmt) in + let (_, mt), stmt, cs = tx (pf, hyps) cpos (pre, post) (me, stmt) in let concl = match side with - | `Left -> f_equivS_r { es with es_ml = me; es_sl = stmt; } - | `Right -> f_equivS_r { es with es_mr = me; es_sr = stmt; } + | `Left -> f_equivS mt (snd es.es_mr) (es_pr es) stmt es.es_sr (es_po es) + | `Right -> f_equivS (snd es.es_ml) mt (es_pr es) es.es_sl stmt (es_po es) in FApi.xmutate1 tc (tr (Some side)) (cs @ [concl]) diff --git a/src/ecMatching.ml b/src/ecMatching.ml index 5d06b827b..2b712ea85 100644 --- a/src/ecMatching.ml +++ b/src/ecMatching.ml @@ -684,9 +684,15 @@ let f_match_core opts hyps (ue, ev) f1 f2 = | FhoareF hf1, FhoareF hf2 -> begin if not (EcReduction.EqTest.for_xp env hf1.hf_f hf2.hf_f) then failure (); - let mxs = Mid.add EcFol.mhr EcFol.mhr mxs in + let subst = + if id_equal hf1.hf_m hf2.hf_m then + subst + else + Fsubst.f_bind_mem subst hf1.hf_m hf2.hf_m in + assert (not (Mid.mem hf1.hf_m mxs) && not (Mid.mem hf2.hf_m mxs)); + let mxs = Mid.add hf1.hf_m hf2.hf_m mxs in List.iter2 (doit env (subst, mxs)) - [hf1.hf_pr; hf1.hf_po] [hf2.hf_pr; hf2.hf_po] + [(hf_pr hf1).inv; (hf_po hf1).inv] [(hf_pr hf2).inv; (hf_po hf2).inv] end | FbdHoareF hf1, FbdHoareF hf2 -> begin @@ -717,8 +723,9 @@ let f_match_core opts hyps (ue, ev) f1 f2 = failure (); doit_mem env mxs pr1.pr_mem pr2.pr_mem; doit env (subst, mxs) pr1.pr_args pr2.pr_args; - let mxs = Mid.add EcFol.mhr EcFol.mhr mxs in - doit env (subst, mxs) pr1.pr_event pr2.pr_event; + let ev1, ev2 = pr1.pr_event, pr2.pr_event in + let mxs = Mid.add ev1.m ev2.m mxs in + doit env (subst, mxs) ev1.inv ev2.inv; end | _, _ -> failure () @@ -985,22 +992,23 @@ module FPosition = struct | Fpr pr -> let subctxt = Sid.add pr.pr_mem ctxt in - doit pos (`WithSubCtxt [(ctxt, pr.pr_args); (subctxt, pr.pr_event)]) + let subctxt = Sid.add pr.pr_event.m subctxt in + doit pos (`WithSubCtxt [(ctxt, pr.pr_args); (subctxt, pr.pr_event.inv)]) | FhoareF hs -> - doit pos (`WithCtxt (Sid.add EcFol.mhr ctxt, [hs.hf_pr; hs.hf_po])) + doit pos (`WithCtxt (Sid.add hs.hf_m ctxt, [(hf_pr hs).inv; (hf_po hs).inv])) (* TODO: A: From what I undertand, there is an error there: it should be (subctxt, hs.bhf_bd) *) | FbdHoareF hs -> - let subctxt = Sid.add EcFol.mhr ctxt in + let subctxt = Sid.add hs.bhf_m ctxt in doit pos (`WithSubCtxt ([(subctxt, hs.bhf_pr); (subctxt, hs.bhf_po); ( ctxt, hs.bhf_bd)])) | FequivF es -> - let ctxt = Sid.add EcFol.mleft ctxt in - let ctxt = Sid.add EcFol.mright ctxt in + let ctxt = Sid.add es.ef_ml ctxt in + let ctxt = Sid.add es.ef_mr ctxt in doit pos (`WithCtxt (ctxt, [es.ef_pr; es.ef_po])) | _ -> None @@ -1132,27 +1140,33 @@ module FPosition = struct f_let lv f1' f2' | Fpr pr -> - let (args', event') = as_seq2 (doit p [pr.pr_args; pr.pr_event]) in - f_pr pr.pr_mem pr.pr_fun args' event' + let (args', event') = as_seq2 (doit p [pr.pr_args; pr.pr_event.inv]) in + let m = pr.pr_event.m in + f_pr pr.pr_mem pr.pr_fun args' {m;inv=event'} | FhoareF hf -> - let (hf_pr, hf_po) = as_seq2 (doit p [hf.hf_pr; hf.hf_po]) in - f_hoareF_r { hf with hf_pr; hf_po; } + let (hf_pr, hf_po) = as_seq2 (doit p [(hf_pr hf).inv; (hf_po hf).inv]) in + let m = hf.hf_m in + f_hoareF {m;inv=hf_pr} hf.hf_f {m;inv=hf_po} | FeHoareF hf -> let (ehf_pr, ehf_po) = as_seq2 (doit p [hf.ehf_pr; hf.ehf_po;]) in - f_eHoareF_r { hf with ehf_pr; ehf_po; } + let m = hf.ehf_m in + f_eHoareF {m;inv=ehf_pr} hf.ehf_f {m;inv=ehf_po} | FbdHoareF hf -> let sub = doit p [hf.bhf_pr; hf.bhf_po; hf.bhf_bd] in let (bhf_pr, bhf_po, bhf_bd) = as_seq3 sub in - f_bdHoareF_r { hf with bhf_pr; bhf_po; bhf_bd; } + let m = hf.bhf_m in + f_bdHoareF {m;inv=bhf_pr} hf.bhf_f {m;inv=bhf_po} hf.bhf_cmp {m;inv=bhf_bd} | FequivF ef -> let (ef_pr, ef_po) = as_seq2 (doit p [ef.ef_pr; ef.ef_po]) in - f_equivF_r { ef with ef_pr; ef_po; } + let ml = ef.ef_ml in + let mr = ef.ef_mr in + f_equivF {ml;mr;inv=ef_pr} ef.ef_fl ef.ef_fr {ml;mr;inv=ef_po} | FhoareS _ -> raise InvalidPosition | FeHoareS _ -> raise InvalidPosition diff --git a/src/ecPV.ml b/src/ecPV.ml index 2126bb0f2..4bd4a5319 100644 --- a/src/ecPV.ml +++ b/src/ecPV.ml @@ -179,25 +179,17 @@ module PVM = struct (try find env pv m s with Not_found -> f) | Fglob(mp,m) -> (try find_glob env (EcPath.mident mp) m s with Not_found -> f) - | FequivF _ -> - check_binding EcFol.mleft s; - check_binding EcFol.mright s; + | FequivF {ef_ml=ml;ef_mr=mr} + | FequivS {es_ml=(ml,_); es_mr=(mr,_)} -> + check_binding ml s; + check_binding mr s; EcFol.f_map (fun ty -> ty) aux f - | FequivS es -> - check_binding (fst es.es_ml) s; - check_binding (fst es.es_mr) s; - EcFol.f_map (fun ty -> ty) aux f - | FhoareF _ | FbdHoareF _ -> - check_binding EcFol.mhr s; - EcFol.f_map (fun ty -> ty) aux f - | FhoareS hs -> - check_binding (fst hs.hs_m) s; - EcFol.f_map (fun ty -> ty) aux f - | FbdHoareS hs -> - check_binding (fst hs.bhs_m) s; - EcFol.f_map (fun ty -> ty) aux f - | Fpr pr -> - check_binding pr.pr_mem s; + | FhoareF {hf_m=m} + | FhoareS {hs_m=(m,_)} + | FbdHoareF {bhf_m=m} + | FbdHoareS {bhs_m=(m,_)} + | Fpr {pr_mem=m} -> + check_binding m s; EcFol.f_map (fun ty -> ty) aux f | Fquant(q,b,f1) -> let f1 = @@ -255,7 +247,7 @@ module PV = struct | Fglob(mp,_) -> { fv with s_gl = Sm.add (EcPath.mident mp) fv.s_gl} | _ -> assert false in - aux fv f + aux fv f.inv let remove env pv fv = { fv with s_pv = Mnpv.remove (pvm env pv) fv.s_pv } @@ -337,36 +329,37 @@ module PV = struct aux env fv e | FhoareF hf -> - in_mem_scope env fv [mhr] [hf.hf_pr; hf.hf_po] + in_mem_scope env fv [hf.hf_m] [(hf_pr hf).inv; (hf_po hf).inv] | FhoareS hs -> in_mem_scope env fv [fst hs.hs_m] [hs.hs_pr; hs.hs_po] | FeHoareF hf -> - in_mem_scope env fv [mhr] [hf.ehf_pr; hf.ehf_po] + in_mem_scope env fv [hf.ehf_m] [hf.ehf_pr; hf.ehf_po] | FeHoareS hs -> in_mem_scope env fv [fst hs.ehs_m] [hs.ehs_pr; hs.ehs_po] | FbdHoareF bhf -> - in_mem_scope env fv [mhr] [bhf.bhf_pr; bhf.bhf_po; bhf.bhf_bd] + in_mem_scope env fv [bhf.bhf_m] [bhf.bhf_pr; bhf.bhf_po; bhf.bhf_bd] | FbdHoareS bhs -> in_mem_scope env fv [fst bhs.bhs_m] [bhs.bhs_pr; bhs.bhs_po; bhs.bhs_bd] | FequivF ef -> - in_mem_scope env fv [mleft; mright] [ef.ef_pr; ef.ef_po] + in_mem_scope env fv [ef.ef_ml; ef.ef_mr] [ef.ef_pr; ef.ef_po] | FequivS es -> in_mem_scope env fv [fst es.es_ml; fst es.es_mr] [es.es_pr; es.es_po] | FeagerF eg -> - in_mem_scope env fv [mhr] [eg.eg_pr; eg.eg_po] + in_mem_scope env fv [eg.eg_ml; eg.eg_mr] [eg.eg_pr; eg.eg_po] | Fpr pr -> let fv = aux env fv pr.pr_args in - in_mem_scope env fv [pr.pr_mem] [pr.pr_event] + let ev = pr.pr_event in + in_mem_scope env fv [ev.m] [ev.inv] and in_mem_scope env fv mems fs = if List.exists (EcIdent.id_equal m) mems @@ -785,16 +778,21 @@ module Mpv2 = struct let x = pvm env x in Mnpv.exists (fun _ (s,_) -> Snpv.mem x s) eqs.s_pv - let to_form ml mr eqs inv = + let to_form eqs ml mr inv = let l = Sm.fold (fun m l -> f_eqglob m ml m mr :: l) eqs.s_gl [] in let l = Mnpv.fold (fun pvl (s,ty) l -> - Snpv.fold (fun pvr l -> f_eq (f_pvar pvl ty ml) (f_pvar pvr ty mr) :: l) + Snpv.fold (fun pvr l -> f_eq (f_pvar pvl ty ml).inv (f_pvar pvr ty mr).inv :: l) s l) eqs.s_pv l in f_and_simpl (f_ands l) inv - let of_form env ml mr f = + + let to_form_ts_inv eqs inv = + map_ts_inv1 (to_form eqs inv.ml inv.mr) inv + + let of_form env f = + let ml, mr = f.ml, f.mr in let rec aux f eqs = match sform_of_form f with | SFtrue -> eqs @@ -816,7 +814,7 @@ module Mpv2 = struct List.fold_left2 (fun eqs f1 f2 -> aux (f_eq f1 f2) eqs) eqs fs1 fs2 | SFand(_, (f1, f2)) -> aux f1 (aux f2 eqs) | _ -> raise Not_found in - aux f empty + aux f.inv empty let enter_local env local ids1 ids2 = try @@ -826,7 +824,8 @@ module Mpv2 = struct List.fold_left2 do1 local ids1 ids2 with _ -> raise EqObsInError - let needed_eq env ml mr f = + let needed_eq env f = + let ml, mr = f.ml, f.mr in let rec add_eq local eqs f1 f2 = match f1.f_node, f2.f_node with @@ -900,8 +899,7 @@ module Mpv2 = struct end | _ -> raise Not_found in - try aux Mid.empty empty f - with _ -> raise Not_found + aux Mid.empty empty f.inv let check_glob eqs = Mnpv.iter (fun pv (s,_)-> @@ -994,7 +992,7 @@ let is_in_refl env lv eqo = | LvTuple lr -> List.exists (fun (pv,_) -> PV.mem_pv env pv eqo) lr let add_eqs_refl env eqo e = - let f = form_of_expr mhr e in + let f = form_of_expr e in let fv = PV.fv env mhr f in PV.union fv eqo diff --git a/src/ecPV.mli b/src/ecPV.mli index dfd3fa0f2..5a70364b6 100644 --- a/src/ecPV.mli +++ b/src/ecPV.mli @@ -1,11 +1,8 @@ (* -------------------------------------------------------------------- *) open EcMaps open EcPath -open EcTypes -open EcModules -open EcMemory open EcEnv -open EcFol +open EcAst (* -------------------------------------------------------------------- *) type alias_clash = @@ -158,9 +155,10 @@ module Mpv2 : sig val empty_local : local val enter_local: env -> local -> (EcIdent.t * ty) list -> (EcIdent.t * ty) list -> local - val to_form : EcIdent.t -> EcIdent.t -> t -> form -> form - val of_form : env -> EcIdent.t -> EcIdent.t -> form -> t - val needed_eq : env -> EcIdent.t -> EcIdent.t -> form -> t + val to_form_ts_inv : t -> ts_inv -> ts_inv + val to_form : t -> memory -> memory -> form -> form + val of_form : env -> ts_inv -> t + val needed_eq : env -> ts_inv -> t val union : t -> t -> t val subset : t -> t -> bool val equal : t -> t -> bool diff --git a/src/ecPrinting.ml b/src/ecPrinting.ml index 7142a6d0b..5d2ffd540 100644 --- a/src/ecPrinting.ml +++ b/src/ecPrinting.ml @@ -58,7 +58,7 @@ module PPEnv = struct | None -> ppe | Some m -> { ppe with - ppe_env = EcEnv.Memory.set_active (fst m) ppe.ppe_env } + ppe_env = EcEnv.Memory.set_active_ss (fst m) ppe.ppe_env } let push_mem ppe ?(active = false) m = let ppe = { ppe with ppe_env = EcEnv.Memory.push m ppe.ppe_env } in @@ -388,6 +388,8 @@ module PPEnv = struct oget (Mint.find_opt i (fst !(ppe.ppe_univar))) end +let debug_mode = true + (* -------------------------------------------------------------------- *) let shorten_path (ppe : PPEnv.t) @@ -566,7 +568,7 @@ let msymbol_of_pv (ppe : PPEnv.t) p = | PVglob xp -> let mem = let env = ppe.PPEnv.ppe_env in - obind (EcEnv.Memory.byid^~ env) (EcEnv.Memory.get_active env) in + obind (EcEnv.Memory.byid^~ env) (EcEnv.Memory.get_active_ss env) in let exception Default in @@ -596,7 +598,7 @@ let pp_pv ppe fmt p = pp_msymbol fmt (msymbol_of_pv ppe p) exception NoProjArg let get_projarg_for_var ppe x i = - let m = oget ~exn:NoProjArg (EcEnv.Memory.current ppe.PPEnv.ppe_env) in + let m = oget ~exn:NoProjArg (EcEnv.Memory.current_ss ppe.PPEnv.ppe_env) in if is_glob x then raise NoProjArg; oget ~exn:NoProjArg (EcMemory.get_name (get_loc x) (Some i) m) @@ -826,14 +828,17 @@ let pp_stype (ppe : PPEnv.t) (fmt : Format.formatter) (ty : ty) = pp_type_r ppe ((1 + fst t_prio_tpl, `NonAssoc), `NonAssoc) fmt ty (* -------------------------------------------------------------------- *) -let pp_mem (ppe : PPEnv.t) (fmt : Format.formatter) (x : memory) = +let pp_mem (ppe : PPEnv.t) (fmt : Format.formatter) (x as id : memory) = let x = Format.sprintf "%s" (PPEnv.local_symb ppe x) in let x = if x <> "" && x.[0] = '&' then String.sub x 1 (String.length x - 1) else x in - Format.fprintf fmt "%s" x + if debug_mode then + Format.fprintf fmt "%s<%s>" x (EcIdent.tostring id) + else + Format.fprintf fmt "%s" x let pp_memtype (ppe : PPEnv.t) (fmt : Format.formatter) (mt : memtype) = match EcMemory.for_printing mt with @@ -1607,7 +1612,7 @@ and try_pp_form_eqveq (ppe : PPEnv.t) _outer fmt f = try let x1 = get_f_projarg ppe f1 i1 ty1 in let x2 = get_f_projarg ppe f2 i2 ty2 in - collect1 (f_eq x1 x2) + collect1 (f_eq x1.inv x2.inv) with NoProjArg -> None end @@ -1744,8 +1749,9 @@ and match_pp_notations let ue = EcUnify.UniEnv.create None in let ov = EcUnify.UniEnv.opentvi ue tv None in let hy = EcEnv.LDecl.init ppe.PPEnv.ppe_env [] in - let mr = odfl mhr (EcEnv.Memory.get_active ppe.PPEnv.ppe_env) in - let bd = form_of_expr mr nt.ont_body in + let bd = match (EcEnv.Memory.get_active_ss ppe.PPEnv.ppe_env) with + | None -> form_of_expr nt.ont_body + | Some m -> (ss_inv_of_expr m nt.ont_body).inv in let bd = Fsubst.f_subst_tvar ~freshen:true ov bd in try @@ -1855,9 +1861,9 @@ and pp_form_core_r | PVloc x -> Ssym.mem x ppe.ppe_inuse | PVglob _ -> false in - if force then default true else + if force || debug_mode then default true else - match EcEnv.Memory.get_active ppe.PPEnv.ppe_env with + match EcEnv.Memory.get_active_ss ppe.PPEnv.ppe_env with | Some i' when EcMemory.mem_equal i i' -> Format.fprintf fmt "%a" (pp_pv ppe) x | _ -> @@ -1865,7 +1871,7 @@ and pp_form_core_r end | Fglob (mp, i) -> begin - match EcEnv.Memory.get_active ppe.PPEnv.ppe_env with + match EcEnv.Memory.get_active_ss ppe.PPEnv.ppe_env with | Some i' when EcMemory.mem_equal i i' -> Format.fprintf fmt "(glob %a)" (pp_topmod ppe) (EcPath.mident mp) | _ -> @@ -1919,29 +1925,43 @@ and pp_form_core_r | Fproj (e1, i) -> begin try let v = get_f_projarg ppe e1 i f.f_ty in - pp_form_core_r ppe outer fmt v + pp_form_core_r ppe outer fmt v.inv with NoProjArg -> pp_proji ppe pp_form_r fmt (e1, i) end | FhoareF hf -> - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.hf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.hf_m hf.hf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in - Format.fprintf fmt "hoare[@[@ %a :@ @[%a ==>@ %a@]@]]" - (pp_funname ppe) hf.hf_f - (pp_form ppepr) hf.hf_pr - (pp_form ppepo) hf.hf_po + if debug_mode then + Format.fprintf fmt "hoare[@[@ %a {%a} :@ @[%a ==>@ %a@]@]]" + (pp_funname ppe) hf.hf_f + (pp_mem ppe) hf.hf_m + (pp_form ppepr) (hf_pr hf).inv + (pp_form ppepo) (hf_po hf).inv + else + Format.fprintf fmt "hoare[@[@ %a :@ @[%a ==>@ %a@]@]]" + (pp_funname ppe) hf.hf_f + (pp_form ppepr) (hf_pr hf).inv + (pp_form ppepo) (hf_po hf).inv | FhoareS hs -> let ppe = PPEnv.push_mem ppe ~active:true hs.hs_m in - Format.fprintf fmt "hoare[@[@ %a :@ @[%a ==>@ %a@]@]]" + if debug_mode then + Format.fprintf fmt "hoare[@[@ %a {%a} :@ @[%a ==>@ %a@]@]]" (pp_stmt_for_form ppe) hs.hs_s + (pp_mem ppe) (fst hs.hs_m) (pp_form ppe) hs.hs_pr (pp_form ppe) hs.hs_po + else + Format.fprintf fmt "hoare[@[@ %a :@ @[%a ==>@ %a@]@]]" + (pp_stmt_for_form ppe) hs.hs_s + (pp_form ppe) hs.hs_pr + (pp_form ppe) hs.hs_po | FeHoareF hf -> - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.ehf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.ehf_m hf.ehf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in Format.fprintf fmt @@ -1959,14 +1979,23 @@ and pp_form_core_r | FequivF eqv -> let (meprl, meprr), (mepol,mepor) = - EcEnv.Fun.equivF_memenv eqv.ef_fl eqv.ef_fr ppe.PPEnv.ppe_env in + EcEnv.Fun.equivF_memenv eqv.ef_ml eqv.ef_mr eqv.ef_fl eqv.ef_fr ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mems ppe [meprl; meprr] in let ppepo = PPEnv.create_and_push_mems ppe [mepol; mepor] in - Format.fprintf fmt "equiv[@[@ %a ~@ %a :@ @[%a ==>@ %a@]@]]" + if debug_mode then + Format.fprintf fmt "equiv[@[@ %a {%a} ~@ %a {%a} :@ @[%a ==>@ %a@]@]]" (pp_funname ppe) eqv.ef_fl + (pp_mem ppe) eqv.ef_ml (pp_funname ppe) eqv.ef_fr + (pp_mem ppe) eqv.ef_mr (pp_form ppepr) eqv.ef_pr (pp_form ppepo) eqv.ef_po + else + Format.fprintf fmt "equiv[@[@ %a ~@ %a :@ @[%a ==>@ %a@]@]]" + (pp_funname ppe) eqv.ef_fl + (pp_funname ppe) eqv.ef_fr + (pp_form ppepr) eqv.ef_pr + (pp_form ppepo) eqv.ef_po | FequivS es -> let ppef = PPEnv.push_mems ppe [es.es_ml; es.es_mr] in @@ -1980,7 +2009,7 @@ and pp_form_core_r | FeagerF eg -> let (meprl, meprr), (mepol,mepor) = - EcEnv.Fun.equivF_memenv eg.eg_fl eg.eg_fr ppe.PPEnv.ppe_env in + EcEnv.Fun.equivF_memenv eg.eg_ml eg.eg_mr eg.eg_fl eg.eg_fr ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mems ppe [meprl; meprr] in let ppepo = PPEnv.create_and_push_mems ppe [mepol; mepor] in Format.fprintf fmt "eager[@[@ %a,@ %a ~@ %a,@ %a :@ @[%a ==>@ %a@]@]]" @@ -1993,15 +2022,24 @@ and pp_form_core_r (pp_form ppepo) eg.eg_po | FbdHoareF hf -> - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.bhf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.bhf_m hf.bhf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in - Format.fprintf fmt "phoare[@[@ %a :@ @[%a ==>@ %a@]@]] %s %a" - (pp_funname ppe) hf.bhf_f - (pp_form ppepr) hf.bhf_pr - (pp_form ppepo) hf.bhf_po - (string_of_hcmp hf.bhf_cmp) - (pp_form_r ppepr (max_op_prec,`NonAssoc)) hf.bhf_bd + if debug_mode then + Format.fprintf fmt "phoare[@[@ %a {%a} :@ @[%a ==>@ %a@]@]] %s %a" + (pp_funname ppe) hf.bhf_f + (pp_mem ppe) hf.bhf_m + (pp_form ppepr) hf.bhf_pr + (pp_form ppepo) hf.bhf_po + (string_of_hcmp hf.bhf_cmp) + (pp_form_r ppepr (max_op_prec,`NonAssoc)) hf.bhf_bd + else + Format.fprintf fmt "phoare[@[@ %a :@ @[%a ==>@ %a@]@]] %s %a" + (pp_funname ppe) hf.bhf_f + (pp_form ppepr) hf.bhf_pr + (pp_form ppepo) hf.bhf_po + (string_of_hcmp hf.bhf_cmp) + (pp_form_r ppepr (max_op_prec,`NonAssoc)) hf.bhf_bd | FbdHoareS hs -> let ppef = PPEnv.push_mem ppe ~active:true hs.bhs_m in @@ -2026,7 +2064,7 @@ and pp_form_core_r | _ -> (fun fmt -> Format.fprintf fmt "(%a)" (pp_form ppe) pr.pr_args)) (pp_local ppe) pr.pr_mem - (pp_form ppep) pr.pr_event + (pp_form ppep) pr.pr_event.inv and pp_form_r (ppe : PPEnv.t) @@ -2049,8 +2087,10 @@ and pp_form ppe fmt f = pp_form_r ppe (min_op_prec, `NonAssoc) fmt f and pp_expr ppe fmt e = - let mr = odfl mhr (EcEnv.Memory.get_active ppe.PPEnv.ppe_env) in - pp_form ppe fmt (form_of_expr mr e) + let f = match (EcEnv.Memory.get_active_ss ppe.PPEnv.ppe_env) with + | None -> form_of_expr e + | Some m -> (ss_inv_of_expr m e).inv in + pp_form ppe fmt f and pp_tuple_expr ppe fmt e = match e.e_node with @@ -2942,13 +2982,16 @@ let pp_post (ppe : PPEnv.t) ?prpo fmt post = (* -------------------------------------------------------------------- *) let pp_hoareF (ppe : PPEnv.t) ?prpo fmt hf = - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.hf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.hf_m hf.hf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in - Format.fprintf fmt "%a@\n%!" (pp_pre ppepr ?prpo) hf.hf_pr; - Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.hf_f; - Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) hf.hf_po + Format.fprintf fmt "%a@\n%!" (pp_pre ppepr ?prpo) (hf_pr hf).inv; + if debug_mode then + Format.fprintf fmt " %a {%a}@\n%!" (pp_funname ppe) hf.hf_f (pp_mem ppe) hf.hf_m + else + Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.hf_f; + Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) (hf_po hf).inv (* -------------------------------------------------------------------- *) @@ -2957,7 +3000,8 @@ let pp_hoareS (ppe : PPEnv.t) ?prpo fmt hs = let ppnode = collect2_s ppef hs.hs_s.s_node [] in let ppnode = c_ppnode ~width:ppe.PPEnv.ppe_width ppef ppnode in - Format.fprintf fmt "Context : %a@\n%!" (pp_memtype ppe) (snd hs.hs_m); + Format.fprintf fmt "Context : %a: %a@\n%!" (pp_mem ppe) (fst hs.hs_m) + (pp_memtype ppe) (snd hs.hs_m); Format.fprintf fmt "@\n%!"; Format.fprintf fmt "%a%!" (pp_pre ppef ?prpo) hs.hs_pr; Format.fprintf fmt "@\n%!"; @@ -2967,12 +3011,15 @@ let pp_hoareS (ppe : PPEnv.t) ?prpo fmt hs = (* -------------------------------------------------------------------- *) let pp_eHoareF (ppe : PPEnv.t) ?prpo fmt hf = - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.ehf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.ehf_m hf.ehf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in Format.fprintf fmt "%a@\n%!" (pp_pre ppepr ?prpo) hf.ehf_pr; - Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.ehf_f; + if debug_mode then + Format.fprintf fmt " %a {%a}@\n%!" (pp_funname ppe) hf.ehf_f (pp_mem ppe) hf.ehf_m + else + Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.ehf_f; Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) hf.ehf_po (* -------------------------------------------------------------------- *) @@ -2982,7 +3029,8 @@ let pp_eHoareS (ppe : PPEnv.t) ?prpo fmt hs = let ppnode = collect2_s ppef hs.ehs_s.s_node [] in let ppnode = c_ppnode ~width:ppe.PPEnv.ppe_width ppef ppnode in - Format.fprintf fmt "Context : %a@\n%!" (pp_memtype ppe) (snd hs.ehs_m); + Format.fprintf fmt "Context : %a: %a@\n%!" (pp_mem ppe) (fst hs.ehs_m) + (pp_memtype ppe) (snd hs.ehs_m); Format.fprintf fmt "@\n%!"; Format.fprintf fmt "%a%!" (pp_pre ppef ?prpo) hs.ehs_pr; Format.fprintf fmt "@\n%!"; @@ -2999,14 +3047,17 @@ let string_of_hrcmp = function (* -------------------------------------------------------------------- *) let pp_bdhoareF (ppe : PPEnv.t) ?prpo fmt hf = - let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.bhf_f ppe.PPEnv.ppe_env in + let mepr, mepo = EcEnv.Fun.hoareF_memenv hf.bhf_m hf.bhf_f ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mem ppe ~active:true mepr in let ppepo = PPEnv.create_and_push_mem ppe ~active:true mepo in let scmp = string_of_hrcmp hf.bhf_cmp in Format.fprintf fmt "%a@\n%!" (pp_pre ppepr ?prpo) hf.bhf_pr; - Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.bhf_f; + if debug_mode then + Format.fprintf fmt " %a {%a}@\n%!" (pp_funname ppe) hf.bhf_f (pp_mem ppe) hf.bhf_m + else + Format.fprintf fmt " %a@\n%!" (pp_funname ppe) hf.bhf_f; Format.fprintf fmt " %s @[%a@]@\n%!" scmp (pp_form ppepr) hf.bhf_bd; Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) hf.bhf_po @@ -3018,8 +3069,8 @@ let pp_bdhoareS (ppe : PPEnv.t) ?prpo fmt hs = in let scmp = string_of_hrcmp hs.bhs_cmp in - - Format.fprintf fmt "Context : %a@\n%!" (pp_memtype ppe) (snd hs.bhs_m); + Format.fprintf fmt "Context : %a: %a@\n%!" (pp_mem ppe) (fst hs.bhs_m) + (pp_memtype ppe) (snd hs.bhs_m); Format.fprintf fmt "Bound : @[%s %a@]@\n%!" scmp (pp_form ppef) hs.bhs_bd; Format.fprintf fmt "@\n%!"; Format.fprintf fmt "%a%!" (pp_pre ppef ?prpo) hs.bhs_pr; @@ -3031,14 +3082,23 @@ let pp_bdhoareS (ppe : PPEnv.t) ?prpo fmt hs = (* -------------------------------------------------------------------- *) let pp_equivF (ppe : PPEnv.t) ?prpo fmt ef = let (meprl, meprr), (mepol,mepor) = - EcEnv.Fun.equivF_memenv ef.ef_fl ef.ef_fr ppe.PPEnv.ppe_env in + EcEnv.Fun.equivF_memenv ef.ef_ml ef.ef_mr ef.ef_fl ef.ef_fr ppe.PPEnv.ppe_env in let ppepr = PPEnv.create_and_push_mems ppe [meprl; meprr] in let ppepo = PPEnv.create_and_push_mems ppe [mepol; mepor] in Format.fprintf fmt "%a@\n%!" (pp_pre ppepr ?prpo) ef.ef_pr; - Format.fprintf fmt " %a ~ %a@\n%!" - (pp_funname ppe) ef.ef_fl - (pp_funname ppe) ef.ef_fr; - Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) ef.ef_po + if debug_mode then begin + Format.fprintf fmt " %a {%a} ~ %a {%a}@\n%!" + (pp_funname ppe) ef.ef_fl + (pp_mem ppe) ef.ef_ml + (pp_funname ppe) ef.ef_fr + (pp_mem ppe) ef.ef_mr; + Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) ef.ef_po; + end else begin + Format.fprintf fmt " %a ~ %a@\n%!" + (pp_funname ppe) ef.ef_fl + (pp_funname ppe) ef.ef_fr; + Format.fprintf fmt "@\n%a%!" (pp_post ppepo ?prpo) ef.ef_po + end (* -------------------------------------------------------------------- *) let pp_equivS (ppe : PPEnv.t) ?prpo fmt es = @@ -3821,6 +3881,12 @@ end (* ------------------------------------------------------------------ *) let () = EcEnv.pp_debug_form := - (fun env fmt f -> + (fun env f -> + let fmt = Format.std_formatter in let ppe = PPEnv.ofenv env in - pp_form ppe fmt f) + Format.pp_print_newline fmt (); + Format.pp_print_newline fmt (); + pp_form ppe fmt f; + Format.pp_print_newline fmt (); + Format.pp_print_newline fmt (); + Format.pp_print_flush fmt ();); diff --git a/src/ecProcSem.ml b/src/ecProcSem.ml index 808ea8674..26df3e622 100644 --- a/src/ecProcSem.ml +++ b/src/ecProcSem.ml @@ -82,8 +82,8 @@ let rec translate_i (env : senv) (cont : senv -> mode * expr) (i : instr) = let tyb = body.e_ty in let aout = - let d = form_of_expr mhr d in - let body = form_of_expr mhr body in + let d = form_of_expr d in + let body = form_of_expr body in let body = let arg = EcIdent.create "arg" in let body = f_let lv (f_local arg tya) body in @@ -93,7 +93,7 @@ let rec translate_i (env : senv) (cont : senv -> mode * expr) (i : instr) = | `Det -> f_dmap tya tyb d body | `Distr -> f_dlet_simpl tya (oget (as_tdistr tyb)) d body - in (`Distr, expr_of_form mhr aout) + in (`Distr, expr_of_form aout) end | Sif (e, bt, bf) -> @@ -143,7 +143,7 @@ let rec translate_i (env : senv) (cont : senv -> mode * expr) (i : instr) = (cmode, e_let lv (e_if e bt bf) c) | `Distr, `Det -> - let body = form_of_expr mhr (e_if e bt bf) in + let body = form_of_expr (e_if e bt bf) in let tya = oget (as_tdistr body.f_ty) in let v = EcIdent.create "v" in let vx = f_local v tya in @@ -154,12 +154,12 @@ let rec translate_i (env : senv) (cont : senv -> mode * expr) (i : instr) = body (f_lambda [v, GTty tya] - (f_let lv vx (form_of_expr mhr c))) + (f_let lv vx (form_of_expr c))) - in (`Distr, expr_of_form mhr aout) + in (`Distr, expr_of_form aout) | `Distr, `Distr -> - let body = form_of_expr mhr (e_if e bt bf) in + let body = form_of_expr (e_if e bt bf) in let tya = oget (as_tdistr body.f_ty) in let tyb = oget (as_tdistr c.e_ty) in let v = EcIdent.create "v" in @@ -171,9 +171,9 @@ let rec translate_i (env : senv) (cont : senv -> mode * expr) (i : instr) = body (f_lambda [v, GTty tya] - (f_let lv vx (form_of_expr mhr c))) + (f_let lv vx (form_of_expr c))) - in (`Distr, expr_of_form mhr aout) + in (`Distr, expr_of_form aout) end @@ -346,13 +346,13 @@ and translate_forloop (env : senv) (cont : senv -> mode * expr) (s : stmt) = | ids -> LTuple ids in - let niter = form_of_expr mhr (translate_e env bd) in + let niter = form_of_expr (translate_e env bd) in let niter = f_proj_simpl (f_int_edivz_simpl niter (f_int inc)) 0 tint in let rem = f_proj_simpl (f_int_edivz_simpl niter (f_int inc)) 1 tint in let outv = f_int_add_simpl (f_int_mul_simpl niter (f_int inc)) rem in - let niter = expr_of_form mhr niter in - let outv = expr_of_form mhr outv in + let niter = expr_of_form niter in + let outv = expr_of_form outv in let mode, aout = match mode with @@ -395,11 +395,11 @@ and translate_forloop (env : senv) (cont : senv -> mode * expr) (s : stmt) = let aout = ctor aty c.e_ty - (form_of_expr mhr aout) + (form_of_expr aout) (f_lambda [(arg, GTty aty)] - (f_let lv (f_local arg aty) (form_of_expr mhr c))) in - (`Distr, expr_of_form mhr aout) + (f_let lv (f_local arg aty) (form_of_expr c))) in + (`Distr, expr_of_form aout) in Some (mode, e_let (LSymbol (x, tint)) outv aout) diff --git a/src/ecProofTyping.ml b/src/ecProofTyping.ml index b7676c6d0..5522383a4 100644 --- a/src/ecProofTyping.ml +++ b/src/ecProofTyping.ml @@ -5,6 +5,7 @@ open EcTypes open EcFol open EcEnv open EcCoreGoal +open EcAst module Msym = EcSymbols.Msym @@ -106,9 +107,11 @@ let tc1_process_prhl_form_opt tc oty pf = | _ -> assert false in - let hyps = LDecl.push_all [ml; mr] hyps in + let hyps = LDecl.push_active_ts ml mr hyps in let mv = Msym.of_list [("pre", pr); ("post", po)] in - pf_process_form_opt ~mv !!tc hyps oty pf + let f = pf_process_form_opt ~mv !!tc hyps oty pf in + let ml, mr = fst ml, fst mr in + {ml;mr;inv=f} let tc1_process_prhl_form tc ty pf = tc1_process_prhl_form_opt tc (Some ty) pf @@ -119,7 +122,7 @@ let tc1_process_prhl_formula tc pf = (* ------------------------------------------------------------------ *) let tc1_process_stmt ?map tc mt c = let hyps = FApi.tc1_hyps tc in - let hyps = LDecl.push_active (mhr,mt) hyps in + let hyps = LDecl.push_active_ss (mhr,mt) hyps in let env = LDecl.toenv hyps in let ue = unienv_of_hyps hyps in let c = Exn.recast_pe !!tc hyps (fun () -> EcTyping.transstmt ?map env ue c) in @@ -139,7 +142,7 @@ let tc1_process_Xhl_exp tc side ty e = let hyps, concl = FApi.tc1_flat tc in let m = fst (EcFol.destr_programS side concl) in - let hyps = LDecl.push_active m hyps in + let hyps = LDecl.push_active_ss m hyps in pf_process_exp !!tc hyps `InProc ty e (* ------------------------------------------------------------------ *) @@ -155,7 +158,7 @@ let tc1_process_Xhl_form ?side tc ty pf = | _ -> None in - let hyps = LDecl.push_active m hyps in + let hyps = LDecl.push_active_ss m hyps in let mv = Option.map @@ -163,7 +166,7 @@ let tc1_process_Xhl_form ?side tc ty pf = mv in - (m, pf_process_form ?mv !!tc hyps ty pf) + (snd m, {m=fst m;inv=pf_process_form ?mv !!tc hyps ty pf}) (* ------------------------------------------------------------------ *) let tc1_process_Xhl_formula ?side tc pf = @@ -177,21 +180,21 @@ let tc1_process_Xhl_formula_xreal tc pf = let tc1_process_codepos_range tc (side, cpr) = let me, _ = EcLowPhlGoal.tc1_get_stmt side tc in let env = FApi.tc1_env tc in - let env = EcEnv.Memory.push_active me env in + let env = EcEnv.Memory.push_active_ss me env in EcTyping.trans_codepos_range env cpr (* ------------------------------------------------------------------ *) let tc1_process_codepos tc (side, cpos) = let me, _ = EcLowPhlGoal.tc1_get_stmt side tc in let env = FApi.tc1_env tc in - let env = EcEnv.Memory.push_active me env in + let env = EcEnv.Memory.push_active_ss me env in EcTyping.trans_codepos env cpos (* ------------------------------------------------------------------ *) let tc1_process_codepos1 tc (side, cpos) = let me, _ = EcLowPhlGoal.tc1_get_stmt side tc in let env = FApi.tc1_env tc in - let env = EcEnv.Memory.push_active me env in + let env = EcEnv.Memory.push_active_ss me env in EcTyping.trans_codepos1 env cpos (* ------------------------------------------------------------------ *) diff --git a/src/ecProofTyping.mli b/src/ecProofTyping.mli index 1b1b8487b..35f959f8c 100644 --- a/src/ecProofTyping.mli +++ b/src/ecProofTyping.mli @@ -1,14 +1,11 @@ (* -------------------------------------------------------------------- *) open EcParsetree open EcIdent -open EcTypes -open EcFol open EcDecl -open EcModules open EcEnv open EcCoreGoal -open EcMemory open EcMatching.Position +open EcAst (* -------------------------------------------------------------------- *) type ptnenv = ty Mid.t * EcUnify.unienv @@ -46,15 +43,15 @@ val tc1_process_exp : tcenv1 -> [`InProc|`InOp] -> ty option -> pexpr -> ex val tc1_process_pattern : tcenv1 -> pformula -> ptnenv * form (* Same as previous functions, but for *HL contexts *) -val tc1_process_Xhl_form : ?side:side -> tcenv1 -> ty -> pformula -> memenv * form -val tc1_process_Xhl_formula : ?side:side -> tcenv1 -> pformula -> memenv * form -val tc1_process_Xhl_formula_xreal : tcenv1 -> pformula -> memenv * form +val tc1_process_Xhl_form : ?side:side -> tcenv1 -> ty -> pformula -> memtype * ss_inv +val tc1_process_Xhl_formula : ?side:side -> tcenv1 -> pformula -> memtype * ss_inv +val tc1_process_Xhl_formula_xreal : tcenv1 -> pformula -> memtype * ss_inv val tc1_process_Xhl_exp : tcenv1 -> oside -> ty option -> pexpr -> expr -val tc1_process_prhl_form_opt: tcenv1 -> ty option -> pformula -> form -val tc1_process_prhl_form : tcenv1 -> ty -> pformula -> form -val tc1_process_prhl_formula : tcenv1 -> pformula -> form +val tc1_process_prhl_form_opt: tcenv1 -> ty option -> pformula -> ts_inv +val tc1_process_prhl_form : tcenv1 -> ty -> pformula -> ts_inv +val tc1_process_prhl_formula : tcenv1 -> pformula -> ts_inv val tc1_process_stmt : ?map:EcTyping.ismap -> tcenv1 -> EcMemory.memtype diff --git a/src/ecReduction.ml b/src/ecReduction.ml index 2458e51d7..237a9568b 100644 --- a/src/ecReduction.ml +++ b/src/ecReduction.ml @@ -7,6 +7,7 @@ open EcTypes open EcModules open EcFol open EcEnv +open EcSubst module BI = EcBigInt @@ -449,6 +450,10 @@ let check_binding (env, subst) (x1, gty1) (x2, gty2) = let check_bindings env subst bd1 bd2 = List.fold_left2 check_binding (env,subst) bd1 bd2 +let check_m_binding subst x1 x2 = + if id_equal x1 x2 then subst + else Fsubst.f_bind_mem subst x2 x1 + let check_me_binding env subst (x1,mt1) (x2,mt2) = check_memtype env mt1 mt2; if id_equal x1 x2 then subst @@ -465,7 +470,7 @@ let is_alpha_eq_e env e1 e2 = try check_e env Fsubst.f_subst_id e1 e2; true with NotConv -> false (* -------------------------------------------------------------------- *) -let is_alpha_eq hyps f1 f2 = +let is_alpha_eq ?(subst=Fsubst.f_subst_id) hyps f1 f2 = let env = LDecl.toenv hyps in let error () = raise NotConv in let ensure t = if not t then error () in @@ -548,8 +553,9 @@ let is_alpha_eq hyps f1 f2 = | FhoareF hf1, FhoareF hf2 -> check_xp env subst hf1.hf_f hf2.hf_f; - aux env subst hf1.hf_pr hf2.hf_pr; - aux env subst hf1.hf_po hf2.hf_po + let subst = check_m_binding subst hf1.hf_m hf2.hf_m in + aux env subst hf1.hf_pr hf2.hf_pr [@alert "-priv_pl"]; + aux env subst hf1.hf_po hf2.hf_po [@alert "-priv_pl"] | FhoareS hs1, FhoareS hs2 -> check_s env subst hs1.hs_s hs2.hs_s; @@ -586,8 +592,10 @@ let is_alpha_eq hyps f1 f2 = | FequivF ef1, FequivF ef2 -> check_xp env subst ef1.ef_fl ef2.ef_fl; check_xp env subst ef1.ef_fr ef2.ef_fr; - aux env subst ef1.ef_pr ef2.ef_pr; - aux env subst ef1.ef_po ef2.ef_po + let subst = check_m_binding subst ef1.ef_ml ef2.ef_ml in + let subst = check_m_binding subst ef1.ef_mr ef2.ef_mr in + aux env subst ef1.ef_pr ef2.ef_pr [@alert "-priv_pl"]; + aux env subst ef1.ef_po ef2.ef_po [@alert "-priv_pl"] | FequivS es1, FequivS es2 -> check_s env subst es1.es_sl es2.es_sl; @@ -600,6 +608,8 @@ let is_alpha_eq hyps f1 f2 = | FeagerF eg1, FeagerF eg2 -> check_xp env subst eg1.eg_fl eg2.eg_fl; check_xp env subst eg1.eg_fr eg2.eg_fr; + let subst = check_m_binding subst eg1.eg_ml eg2.eg_ml in + let subst = check_m_binding subst eg1.eg_mr eg2.eg_mr in aux env subst eg1.eg_pr eg2.eg_pr; aux env subst eg1.eg_po eg2.eg_po; check_s env subst eg1.eg_sl eg2.eg_sl; @@ -608,8 +618,9 @@ let is_alpha_eq hyps f1 f2 = | Fpr pr1, Fpr pr2 -> check_mem subst pr1.pr_mem pr2.pr_mem; check_xp env subst pr1.pr_fun pr2.pr_fun; + let subst = check_m_binding subst pr1.pr_event.m pr2.pr_event.m in aux env subst pr1.pr_args pr2.pr_args; - aux env subst pr1.pr_event pr2.pr_event + aux env subst pr1.pr_event.inv pr2.pr_event.inv | _, _ -> error () @@ -618,7 +629,7 @@ let is_alpha_eq hyps f1 f2 = | NotConv -> false in - test env Fsubst.f_subst_id f1 f2 + test env subst f1 f2 (* -------------------------------------------------------------------- *) type reduction_info = { @@ -1050,7 +1061,7 @@ let reduce_head simplify ri env hyps f = subst bds cargs) subst bds pargs in - let body = EcFol.form_of_expr EcFol.mhr body in + let body = EcFol.form_of_expr body in (* FIXME subst-refact can we do both subst in once *) let body = Tvar.f_subst ~freshen:true (List.map fst op.EcDecl.op_tparams) tys body in @@ -1063,7 +1074,7 @@ let reduce_head simplify ri env hyps f = (* μ-reduction *) | Fpvar (pv, m) when ri.modpath -> let f' = f_pvar (NormMp.norm_pvar env pv) f.f_ty m in - if f_equal f f' then raise nohead else f' + if f_equal f f'.inv then raise nohead else f'.inv (* η-reduction *) | Fquant (Llambda, [x, GTty _], { f_node = Fapp (fn, args) }) @@ -1247,25 +1258,30 @@ let rec simplify ri env f = match f.f_node with | FhoareF hf when ri.ri.modpath -> let hf_f = EcEnv.NormMp.norm_xfun env hf.hf_f in - f_map (fun ty -> ty) (simplify ri env) (f_hoareF_r { hf with hf_f }) + f_map (fun ty -> ty) (simplify ri env) + (f_hoareF (hf_pr hf) hf_f (hf_po hf)) | FeHoareF hf when ri.ri.modpath -> let ehf_f = EcEnv.NormMp.norm_xfun env hf.ehf_f in - f_map (fun ty -> ty) (simplify ri env) (f_eHoareF_r { hf with ehf_f }) + f_map (fun ty -> ty) (simplify ri env) + (f_eHoareF (ehf_pr hf) ehf_f (ehf_po hf)) | FbdHoareF hf when ri.ri.modpath -> let bhf_f = EcEnv.NormMp.norm_xfun env hf.bhf_f in - f_map (fun ty -> ty) (simplify ri env) (f_bdHoareF_r { hf with bhf_f }) + f_map (fun ty -> ty) (simplify ri env) + (f_bdHoareF (bhf_pr hf) bhf_f (bhf_po hf) hf.bhf_cmp (bhf_bd hf)) | FequivF ef when ri.ri.modpath -> let ef_fl = EcEnv.NormMp.norm_xfun env ef.ef_fl in let ef_fr = EcEnv.NormMp.norm_xfun env ef.ef_fr in - f_map (fun ty -> ty) (simplify ri env) (f_equivF_r { ef with ef_fl; ef_fr; }) + f_map (fun ty -> ty) (simplify ri env) + (f_equivF (ef_pr ef) ef_fl ef_fr (ef_po ef)) | FeagerF eg when ri.ri.modpath -> let eg_fl = EcEnv.NormMp.norm_xfun env eg.eg_fl in let eg_fr = EcEnv.NormMp.norm_xfun env eg.eg_fr in - f_map (fun ty -> ty) (simplify ri env) (f_eagerF_r { eg with eg_fl ; eg_fr; }) + f_map (fun ty -> ty) (simplify ri env) + (f_eagerF (eg_pr eg) eg.eg_sl eg_fl eg_fr eg.eg_sr (eg_po eg)) | Fpr pr when ri.ri.modpath -> let pr_fun = EcEnv.NormMp.norm_xfun env pr.pr_fun in @@ -1345,25 +1361,35 @@ let zpop ri side f hd = | Ztuple, args -> f_tuple args | Zproj i, [f1] -> f_proj f1 i hd.se_ty | Zhl {f_node = FhoareF hf}, [pr;po] -> - f_hoareF_r {hf with hf_pr = pr; hf_po = po } + let m = hf.hf_m in + f_hoareF {m;inv=pr} hf.hf_f {m;inv=po} | Zhl {f_node = FhoareS hs}, [pr;po] -> - f_hoareS_r {hs with hs_pr = pr; hs_po = po } + let m = fst hs.hs_m in + f_hoareS (snd hs.hs_m) {m;inv=pr} hs.hs_s {m;inv=po} | Zhl {f_node = FeHoareF hf}, [pr;po] -> - f_eHoareF_r {hf with ehf_pr = pr; ehf_po = po } + let m = hf.ehf_m in + f_eHoareF {m;inv=pr} hf.ehf_f {m;inv=po} | Zhl {f_node = FeHoareS hs}, [pr;po] -> - f_eHoareS_r {hs with ehs_pr = pr; ehs_po = po } + let m = fst hs.ehs_m in + f_eHoareS (snd hs.ehs_m) {m;inv=pr} hs.ehs_s {m;inv=po} | Zhl {f_node = FbdHoareF hf}, [pr;po;bd] -> - f_bdHoareF_r {hf with bhf_pr = pr; bhf_po = po; bhf_bd = bd} + let m = hf.bhf_m in + f_bdHoareF {m;inv=pr} hf.bhf_f {m;inv=po} hf.bhf_cmp {m;inv=bd} | Zhl {f_node = FbdHoareS hs}, [pr;po;bd] -> - f_bdHoareS_r {hs with bhs_pr = pr; bhs_po = po; bhs_bd = bd} - | Zhl {f_node = FequivF hf}, [pr;po] -> - f_equivF_r {hf with ef_pr = pr; ef_po = po } + let m = fst hs.bhs_m in + f_bdHoareS (snd hs.bhs_m) {m;inv=pr} hs.bhs_s {m;inv=po} hs.bhs_cmp {m;inv=bd} + | Zhl {f_node = FequivF ef}, [pr;po] -> + let (ml, mr) = (ef.ef_ml, ef.ef_mr) in + f_equivF {ml;mr;inv=pr} ef.ef_fl ef.ef_fr {ml;mr;inv=po} | Zhl {f_node = FequivS hs}, [pr;po] -> - f_equivS_r {hs with es_pr = pr; es_po = po } + let (ml, mr) = (fst hs.es_ml, fst hs.es_mr) in + f_equivS (snd hs.es_ml) (snd hs.es_mr) {ml;mr;inv=pr} hs.es_sl hs.es_sr + {ml;mr;inv=po} | Zhl {f_node = FeagerF hs}, [pr;po] -> - f_eagerF_r {hs with eg_pr = pr; eg_po = po } + let (ml, mr) = (hs.eg_ml, hs.eg_mr) in + f_eagerF {ml;mr;inv=pr} hs.eg_sl hs.eg_fl hs.eg_fr hs.eg_sr {ml;mr;inv=po} | Zhl {f_node = Fpr hs}, [a;ev] -> - f_pr_r {hs with pr_args = a; pr_event = ev } + f_pr_r {hs with pr_args = a; pr_event = {m=hs.pr_event.m; inv=ev} } | _, _ -> assert false (* -------------------------------------------------------------------- *) @@ -1458,57 +1484,71 @@ let rec conv ri env f1 f2 stk = conv_next ri env f1 stk | FhoareF hf1, FhoareF hf2 when EqTest_i.for_xp env hf1.hf_f hf2.hf_f -> - conv ri env hf1.hf_pr hf2.hf_pr (zhl f1 [hf1.hf_po] [hf2.hf_po] stk) + let pr2 = (ss_inv_rebind (hf_pr hf2) hf1.hf_m).inv in + let po2 = (ss_inv_rebind (hf_po hf2) hf1.hf_m).inv in + conv ri env hf1.hf_pr pr2 (zhl f1 [hf1.hf_po] [po2] stk) [@alert "-priv_pl"] | FhoareS hs1, FhoareS hs2 when EqTest_i.for_stmt env hs1.hs_s hs2.hs_s -> begin match check_me_binding env Fsubst.f_subst_id hs1.hs_m hs2.hs_m with - | subst -> - let subst = Fsubst.f_subst subst in - conv ri env hs1.hs_pr (subst hs2.hs_pr) (zhl f1 [hs1.hs_po] [subst hs2.hs_po] stk) + | _subst -> + let pr2 = (ss_inv_rebind (hs_pr hs2) (fst hs1.hs_m)).inv in + let po2 = (ss_inv_rebind (hs_po hs2) (fst hs1.hs_m)).inv in + conv ri env hs1.hs_pr pr2 (zhl f1 [hs1.hs_po] [po2] stk) | exception NotConv -> force_head ri env f1 f2 stk end | FeHoareF hf1, FeHoareF hf2 when EqTest_i.for_xp env hf1.ehf_f hf2.ehf_f -> - conv ri env hf1.ehf_pr hf2.ehf_pr (zhl f1 [hf1.ehf_po] [hf2.ehf_po] stk) + let pr2 = (ss_inv_rebind (ehf_pr hf2) hf1.ehf_m).inv in + let po2 = (ss_inv_rebind (ehf_po hf2) hf1.ehf_m).inv in + conv ri env hf1.ehf_pr pr2 (zhl f1 [hf1.ehf_po] [po2] stk) | FeHoareS hs1, FeHoareS hs2 when EqTest_i.for_stmt env hs1.ehs_s hs2.ehs_s -> begin match check_me_binding env Fsubst.f_subst_id hs1.ehs_m hs2.ehs_m with - | subst -> - let subst = Fsubst.f_subst subst in - conv ri env hs1.ehs_pr (subst hs2.ehs_pr) (zhl f1 [hs1.ehs_po] [subst hs2.ehs_po] stk) + | _subst -> + let pr2 = (ss_inv_rebind (ehs_pr hs2) (fst hs1.ehs_m)).inv in + let po2 = (ss_inv_rebind (ehs_po hs2) (fst hs1.ehs_m)).inv in + conv ri env hs1.ehs_pr pr2 (zhl f1 [hs1.ehs_po] [po2] stk) | exception NotConv -> force_head ri env f1 f2 stk end | FbdHoareF hf1, FbdHoareF hf2 when EqTest_i.for_xp env hf1.bhf_f hf2.bhf_f && hf1.bhf_cmp = hf2.bhf_cmp -> - conv ri env hf1.bhf_pr hf2.bhf_pr - (zhl f1 [hf1.bhf_po;hf1.bhf_bd] [hf2.bhf_po; hf2.bhf_bd] stk) + let pr2 = (ss_inv_rebind (bhf_pr hf2) hf1.bhf_m).inv in + let po2 = (ss_inv_rebind (bhf_po hf2) hf1.bhf_m).inv in + let bd2 = (ss_inv_rebind (bhf_bd hf2) hf1.bhf_m).inv in + conv ri env hf1.bhf_pr pr2 + (zhl f1 [hf1.bhf_po;hf1.bhf_bd] [po2; bd2] stk) | FbdHoareS hs1, FbdHoareS hs2 when EqTest_i.for_stmt env hs1.bhs_s hs2.bhs_s && hs1.bhs_cmp = hs2.bhs_cmp -> begin match check_me_binding env Fsubst.f_subst_id hs1.bhs_m hs2.bhs_m with - | subst -> - let subst = Fsubst.f_subst subst in - conv ri env hs1.bhs_pr (subst hs2.bhs_pr) - (zhl f1 [hs1.bhs_po;hs1.bhs_bd] (List.map subst [hs2.bhs_po; hs2.bhs_bd]) stk) + | _subst -> + let pr2 = (ss_inv_rebind (bhs_pr hs2) (fst hs1.bhs_m)).inv in + let po2 = (ss_inv_rebind (bhs_po hs2) (fst hs1.bhs_m)).inv in + let bd2 = (ss_inv_rebind (bhs_bd hs2) (fst hs1.bhs_m)).inv in + conv ri env hs1.bhs_pr pr2 + (zhl f1 [hs1.bhs_po;hs1.bhs_bd] [po2; bd2] stk) | exception NotConv -> force_head ri env f1 f2 stk end | FequivF ef1, FequivF ef2 when EqTest_i.for_xp env ef1.ef_fl ef2.ef_fl && EqTest_i.for_xp env ef1.ef_fr ef2.ef_fr -> - conv ri env ef1.ef_pr ef2.ef_pr (zhl f1 [ef1.ef_po] [ef2.ef_po] stk) + let pr2 = (ts_inv_rebind (ef_pr ef2) ef1.ef_ml ef1.ef_mr).inv in + let po2 = (ts_inv_rebind (ef_po ef2) ef1.ef_ml ef1.ef_mr).inv in + conv ri env ef1.ef_pr pr2 (zhl f1 [ef1.ef_po] [po2] stk) | FequivS es1, FequivS es2 when EqTest_i.for_stmt env es1.es_sl es2.es_sl && EqTest_i.for_stmt env es1.es_sr es2.es_sr -> begin match check_me_bindings env Fsubst.f_subst_id [es1.es_ml; es1.es_mr] [es2.es_ml; es2.es_mr] with - | subst -> - let subst = Fsubst.f_subst subst in - conv ri env es1.es_pr (subst es2.es_pr) (zhl f1 [es1.es_po] [subst es2.es_po] stk) + | _subst -> + let pr2 = (ts_inv_rebind (es_pr es2) (fst es1.es_ml) (fst es1.es_mr)).inv in + let po2 = (ts_inv_rebind (es_po es2) (fst es1.es_ml) (fst es1.es_mr)).inv in + conv ri env es1.es_pr pr2 (zhl f1 [es1.es_po] [po2] stk) | exception NotConv -> force_head ri env f1 f2 stk end @@ -1517,14 +1557,17 @@ let rec conv ri env f1 f2 stk = && EqTest_i.for_xp env eg1.eg_fr eg2.eg_fr && EqTest_i.for_stmt env eg1.eg_sl eg2.eg_sl && EqTest_i.for_stmt env eg1.eg_sr eg2.eg_sr then - conv ri env eg1.eg_pr eg2.eg_pr (zhl f1 [eg1.eg_po] [eg2.eg_po] stk) + let pr2 = (ts_inv_rebind (eg_pr eg2) eg1.eg_ml eg1.eg_mr).inv in + let po2 = (ts_inv_rebind (eg_po eg2) eg1.eg_ml eg1.eg_mr).inv in + conv ri env eg1.eg_pr pr2 (zhl f1 [eg1.eg_po] [po2] stk) else force_head ri env f1 f2 stk | Fpr pr1, Fpr pr2 -> if EcMemory.mem_equal pr1.pr_mem pr2.pr_mem && EqTest_i.for_xp env pr1.pr_fun pr2.pr_fun then - conv ri env pr1.pr_args pr2.pr_args (zhl f1 [pr1.pr_event] [pr2.pr_event] stk) + let ev2 = (ss_inv_rebind pr2.pr_event pr1.pr_event.m).inv in + conv ri env pr1.pr_args pr2.pr_args (zhl f1 [pr1.pr_event.inv] [ev2] stk) else force_head ri env f1 f2 stk @@ -1767,13 +1810,22 @@ module User = struct end (* -------------------------------------------------------------------- *) + +let ss_inv_alpha_eq hyps (inv1 : ss_inv) (inv2 : ss_inv) = + let subst = Fsubst.f_bind_mem Fsubst.f_subst_id inv1.m inv2.m in + is_alpha_eq ~subst hyps inv2.inv inv1.inv + +let ts_inv_alpha_eq hyps (inv1 : ts_inv) (inv2 : ts_inv) = + let subst = Fsubst.f_bind_mem Fsubst.f_subst_id inv1.ml inv2.ml in + let subst = Fsubst.f_bind_mem subst inv1.mr inv2.mr in + is_alpha_eq ~subst hyps inv2.inv inv1.inv module EqTest = struct include EqTest_base include EqMod_base(struct let for_expr env ~norm:_ alpha e1 e2 = let convert e = - let f = form_of_expr mhr e in + let f = form_of_expr e in if Mid.is_empty alpha then f else diff --git a/src/ecReduction.mli b/src/ecReduction.mli index 7d5a47dff..116cb8015 100644 --- a/src/ecReduction.mli +++ b/src/ecReduction.mli @@ -1,10 +1,10 @@ (* -------------------------------------------------------------------- *) open EcIdent open EcPath -open EcTypes open EcFol open EcModules open EcEnv +open EcAst (* -------------------------------------------------------------------- *) exception IncompatibleType of env * (ty * ty) @@ -35,7 +35,7 @@ module EqTest : sig val is_int : env -> ty -> bool end -val is_alpha_eq : LDecl.hyps -> form -> form -> bool +val is_alpha_eq : ?subst:f_subst -> LDecl.hyps -> form -> form -> bool (* -------------------------------------------------------------------- *) module User : sig @@ -107,3 +107,6 @@ val check_bindings : type xconv = [`Eq | `AlphaEq | `Conv] val xconv : xconv -> LDecl.hyps -> form -> form -> bool + +val ss_inv_alpha_eq : LDecl.hyps -> ss_inv -> ss_inv -> bool +val ts_inv_alpha_eq : LDecl.hyps -> ts_inv -> ts_inv -> bool \ No newline at end of file diff --git a/src/ecScope.ml b/src/ecScope.ml index 594518314..8329e8499 100644 --- a/src/ecScope.ml +++ b/src/ecScope.ml @@ -1345,7 +1345,7 @@ module Op = struct (`Det, Sem.translate_e env ret) in let mode, aout = Sem.translate_s env cont body.f_body in - let aout = form_of_expr mhr aout in (* FIXME: translate to forms directly? *) + let aout = form_of_expr aout in (* FIXME: translate to forms directly? *) let aout = f_lambda (List.map2 (fun (_, ty) x -> (x, GTty ty)) params ids) aout in let opdecl = EcDecl.{ @@ -1393,7 +1393,7 @@ module Op = struct (f_pr prmem f (f_tuple (List.map (fun (x, ty) -> f_local x ty) locs)) - (f_eq res resv)) + (map_ss_inv1 (fun r -> f_eq r resv) res)) mu)) in @@ -1418,16 +1418,16 @@ module Op = struct f_forall (List.map (fun (x, ty) -> (x, GTty ty)) locs) (f_hoareF - (f_eq - args - (f_tuple (List.map (fun (x, ty) -> f_local x ty) locs))) + {m=mhr;inv=(f_eq + args.inv + (f_tuple (List.map (fun (x, ty) -> f_local x ty) locs)))} f - (f_eq - res + {m=mhr;inv=(f_eq + res.inv (f_app (f_op oppath [] opdecl.op_ty) (List.map (fun (x, ty) -> f_local x ty) locs) - sig_.fs_ret))) + sig_.fs_ret))}) in let prax = EcDecl.{ @@ -2423,7 +2423,7 @@ end let tip = f_subst_init ~tv:tip () in let es = e_subst tip in let xs = List.map (snd_map (ty_subst tip)) nt.ont_args in - let bd = EcFol.form_of_expr EcFol.mhr (es nt.ont_body) in + let bd = EcFol.form_of_expr (es nt.ont_body) in let fp = EcFol.f_lambda (List.map (snd_map EcFol.gtty) xs) bd in match fp.f_node with diff --git a/src/ecSection.ml b/src/ecSection.ml index e6b1eddc4..7a001f6be 100644 --- a/src/ecSection.ml +++ b/src/ecSection.ml @@ -219,13 +219,13 @@ let rec on_form (cb : cb) (f : EcFol.form) = | EcAst.Fpr pr -> on_pr cb pr and on_hf cb hf = - on_form cb hf.EcAst.hf_pr; - on_form cb hf.EcAst.hf_po; + on_form cb (hf_pr hf).inv; + on_form cb (hf_po hf).inv; on_xp cb hf.EcAst.hf_f and on_hs cb hs = - on_form cb hs.EcAst.hs_pr; - on_form cb hs.EcAst.hs_po; + on_form cb (hs_pr hs).inv; + on_form cb (hs_po hs).inv; on_stmt cb hs.EcAst.hs_s; on_memenv cb hs.EcAst.hs_m @@ -278,7 +278,7 @@ let rec on_form (cb : cb) (f : EcFol.form) = and on_pr cb pr = on_xp cb pr.EcAst.pr_fun; - List.iter (on_form cb) [pr.EcAst.pr_event; pr.EcAst.pr_args] + List.iter (on_form cb) [pr.EcAst.pr_event.inv; pr.EcAst.pr_args] in on_ty cb f.EcAst.f_ty; fornode () diff --git a/src/ecSmt.ml b/src/ecSmt.ml index 1e24e6828..42e991b1d 100644 --- a/src/ecSmt.ml +++ b/src/ecSmt.ml @@ -906,8 +906,8 @@ and trans_pr ((genv,lenv) as env) {pr_mem; pr_fun; pr_args; pr_event} = let d = WTerm.t_app ls [warg; wmem] (Some tyr) in let wev = - let lenv, wbd = trans_binding genv lenv (mhr, GTmem mt) in - let wbody = trans_form_b (genv,lenv) pr_event in + let lenv, wbd = trans_binding genv lenv (pr_event.m, GTmem mt) in + let wbody = trans_form_b (genv,lenv) pr_event.inv in trans_lambda genv [wbd] wbody in WTerm.t_app_infer fs_mu [d; wev] @@ -990,7 +990,7 @@ and trans_fix (genv, lenv) (wdom, o) = | OPB_Leaf (locals, e) -> let ctors = List.rev ctors in let lenv, cvs = List.map_fold (trans_lvars genv) lenv locals in - let fe = EcCoreFol.form_of_expr EcCoreFol.mhr e in + let fe = EcCoreFol.form_of_expr e in let we = trans_app (genv, lenv) fe eargs in @@ -1416,7 +1416,7 @@ module Frequency = struct | Fpr pr -> sf := Sx.add pr.pr_fun !sf; - doit pr.pr_event; doit pr.pr_args in + doit pr.pr_event.inv; doit pr.pr_args in doit f; if not (Sx.is_empty !sf) then sp := Sp.add CI_Distr.p_mu !sp; !sp, !sf @@ -1452,7 +1452,7 @@ module Frequency = struct r_union rs (f_ops unwanted_op f) | {op_kind = OB_oper (Some (OP_Fix e)) } -> let rec aux rs = function - | OPB_Leaf (_, e) -> r_union rs (f_ops unwanted_op (form_of_expr mhr e)) + | OPB_Leaf (_, e) -> r_union rs (f_ops unwanted_op (form_of_expr e)) | OPB_Branch bs -> Parray.fold_left (fun rs b -> aux rs b.opb_sub) rs bs in aux rs e.opf_branches @@ -1495,7 +1495,7 @@ module Frequency = struct | Fapp (e, es) -> List.iter add (e :: es) | Ftuple es -> List.iter add es | Fproj (e, _) -> add e - | Fpr pr -> addx pr.pr_fun;add pr.pr_event;add pr.pr_args + | Fpr pr -> addx pr.pr_fun;add pr.pr_event.inv;add pr.pr_args | _ -> () in add form diff --git a/src/ecSubst.ml b/src/ecSubst.ml index 01b48a76a..9173e67c8 100644 --- a/src/ecSubst.ml +++ b/src/ecSubst.ml @@ -126,7 +126,7 @@ let get_def (s : subst) (p : EcPath.path) = | Some (ids, body) -> let body = match body with - | `Op e -> form_of_expr mhr e + | `Op e -> form_of_expr e | `Pred f -> f in Some (ids, body) @@ -503,12 +503,12 @@ let rec subst_form (s : subst) (f : form) = let pv = subst_progvar s pv in let ty = subst_ty s f.f_ty in let m = subst_mem s m in - f_pvar pv ty m + (f_pvar pv ty m).inv | Fglob (mp, m) -> let mp = EcPath.mget_ident (subst_mpath s (EcPath.mident mp)) in let m = subst_mem s m in - f_glob mp m + (f_glob mp m).inv | Fapp ({ f_node = Fop (p, tys) }, args) when has_def s p -> let tys = subst_tys s tys in @@ -529,104 +529,85 @@ let rec subst_form (s : subst) (f : form) = let ty = subst_ty s f.f_ty in f_op p tys ty - | FhoareF { hf_pr; hf_f; hf_po } -> - let hf_pr, hf_po = - let s = add_memory s mhr mhr in - let hf_pr = subst_form s hf_pr in - let hf_po = subst_form s hf_po in - (hf_pr, hf_po) in - let hf_f = subst_xpath s hf_f in + | FhoareF hf -> + let hf_f = subst_xpath s hf.hf_f in + let s = add_memory s hf.hf_m hf.hf_m in + let hf_pr = map_ss_inv1 (subst_form s) (hf_pr hf) in + let hf_po = map_ss_inv1 (subst_form s) (hf_po hf) in f_hoareF hf_pr hf_f hf_po - | FhoareS { hs_m; hs_pr; hs_s; hs_po } -> - let hs_m, (hs_pr, hs_po) = - let s, hs_m = subst_memtype s hs_m in - let hs_pr = subst_form s hs_pr in - let hs_po = subst_form s hs_po in - hs_m, (hs_pr, hs_po) in - let hs_s = subst_stmt s hs_s in - f_hoareS hs_m hs_pr hs_s hs_po - - | FbdHoareF { bhf_pr; bhf_f; bhf_po; bhf_cmp; bhf_bd } -> - let bhf_pr, bhf_po = - let s = add_memory s mhr mhr in - let bhf_pr = subst_form s bhf_pr in - let bhf_po = subst_form s bhf_po in - (bhf_pr, bhf_po) in - let bhf_f = subst_xpath s bhf_f in - let bhf_bd = subst_form s bhf_bd in - f_bdHoareF bhf_pr bhf_f bhf_po bhf_cmp bhf_bd - - | FbdHoareS { bhs_m; bhs_pr; bhs_s; bhs_po; bhs_cmp; bhs_bd } -> - let bhs_m, (bhs_pr, bhs_po, bhs_bd) = - let s, bhs_m = subst_memtype s bhs_m in - let bhs_pr = subst_form s bhs_pr in - let bhs_po = subst_form s bhs_po in - let bhs_bd = subst_form s bhs_bd in - bhs_m, (bhs_pr, bhs_po, bhs_bd) in - let bhs_s = subst_stmt s bhs_s in - f_bdHoareS bhs_m bhs_pr bhs_s bhs_po bhs_cmp bhs_bd - - | FeHoareF { ehf_pr; ehf_f; ehf_po } -> - let ehf_pr, ehf_po = - let s = add_memory s mhr mhr in - let ehf_pr = subst_form s ehf_pr in - let ehf_po = subst_form s ehf_po in - (ehf_pr, ehf_po) in - let ehf_f = subst_xpath s ehf_f in + | FhoareS hs -> + let hs_s = subst_stmt s hs.hs_s in + let s, (_,mt) = subst_memtype s hs.hs_m in + let hs_pr = map_ss_inv1 (subst_form s) (hs_pr hs) in + let hs_po = map_ss_inv1 (subst_form s) (hs_po hs) in + f_hoareS mt hs_pr hs_s hs_po + + | FbdHoareF bhf -> + let bhf_f = subst_xpath s bhf.bhf_f in + let s = add_memory s bhf.bhf_m bhf.bhf_m in + let bhf_pr = map_ss_inv1 (subst_form s) (bhf_pr bhf) in + let bhf_po = map_ss_inv1 (subst_form s) (bhf_po bhf) in + let bhf_bd = map_ss_inv1 (subst_form s) (bhf_bd bhf) in + f_bdHoareF bhf_pr bhf_f bhf_po bhf.bhf_cmp bhf_bd + + | FbdHoareS bhs -> + let bhs_s = subst_stmt s bhs.bhs_s in + let s, (_,mt) = subst_memtype s bhs.bhs_m in + let bhs_pr = map_ss_inv1 (subst_form s) (bhs_pr bhs) in + let bhs_po = map_ss_inv1 (subst_form s) (bhs_po bhs) in + let bhs_bd = map_ss_inv1 (subst_form s) (bhs_bd bhs) in + f_bdHoareS mt bhs_pr bhs_s bhs_po bhs.bhs_cmp bhs_bd + + | FeHoareF ehf -> + let ehf_f = subst_xpath s ehf.ehf_f in + let s = add_memory s ehf.ehf_m ehf.ehf_m in + let ehf_pr = map_ss_inv1 (subst_form s) (ehf_pr ehf) in + let ehf_po = map_ss_inv1 (subst_form s) (ehf_po ehf) in f_eHoareF ehf_pr ehf_f ehf_po - | FeHoareS { ehs_m; ehs_pr; ehs_s; ehs_po } -> - let ehs_m, (ehs_pr, ehs_po) = - let s, ehs_m = subst_memtype s ehs_m in - let ehs_pr = subst_form s ehs_pr in - let ehs_po = subst_form s ehs_po in - ehs_m, (ehs_pr, ehs_po) in - let ehs_s = subst_stmt s ehs_s in - f_eHoareS ehs_m ehs_pr ehs_s ehs_po - - | FequivF { ef_pr; ef_fl; ef_fr; ef_po } -> - let ef_pr, ef_po = - let s = add_memory s mleft mleft in - let s = add_memory s mright mright in - let ef_pr = subst_form s ef_pr in - let ef_po = subst_form s ef_po in - (ef_pr, ef_po) in - let ef_fl = subst_xpath s ef_fl in - let ef_fr = subst_xpath s ef_fr in + | FeHoareS ehs -> + let ehs_s = subst_stmt s ehs.ehs_s in + let s, (_,mt) = subst_memtype s ehs.ehs_m in + let ehs_pr = map_ss_inv1 (subst_form s) (ehs_pr ehs) in + let ehs_po = map_ss_inv1 (subst_form s) (ehs_po ehs) in + f_eHoareS mt ehs_pr ehs_s ehs_po + + | FequivF ef -> + let ef_fl = subst_xpath s ef.ef_fl in + let ef_fr = subst_xpath s ef.ef_fr in + let s = add_memory s ef.ef_ml ef.ef_ml in + let s = add_memory s ef.ef_mr ef.ef_mr in + let ef_pr = map_ts_inv1 (subst_form s) (ef_pr ef) in + let ef_po = map_ts_inv1 (subst_form s) (ef_po ef) in f_equivF ef_pr ef_fl ef_fr ef_po - | FequivS { es_ml; es_mr; es_pr; es_sl; es_sr; es_po } -> - let (es_ml, es_mr), (es_pr, es_po) = - let s, es_ml = subst_memtype s es_ml in - let s, es_mr = subst_memtype s es_mr in - let es_pr = subst_form s es_pr in - let es_po = subst_form s es_po in - (es_ml, es_mr), (es_pr, es_po) in - let es_sl = subst_stmt s es_sl in - let es_sr = subst_stmt s es_sr in - f_equivS es_ml es_mr es_pr es_sl es_sr es_po - - | FeagerF { eg_pr; eg_sl; eg_fl; eg_fr; eg_sr; eg_po } -> - let eg_pr, eg_po = - let s = add_memory s mleft mleft in - let s = add_memory s mright mright in - let eg_pr = subst_form s eg_pr in - let eg_po = subst_form s eg_po in - (eg_pr, eg_po) in - let eg_sl = subst_stmt s eg_sl in - let eg_sr = subst_stmt s eg_sr in - let eg_fl = subst_xpath s eg_fl in - let eg_fr = subst_xpath s eg_fr in + | FequivS es -> + let es_sl = subst_stmt s es.es_sl in + let es_sr = subst_stmt s es.es_sr in + let s, (_,mtl) = subst_memtype s es.es_ml in + let s, (_,mtr) = subst_memtype s es.es_mr in + let es_pr = map_ts_inv1 (subst_form s) (es_pr es) in + let es_po = map_ts_inv1 (subst_form s) (es_po es) in + f_equivS mtl mtr es_pr es_sl es_sr es_po + + | FeagerF eg -> + let eg_sl = subst_stmt s eg.eg_sl in + let eg_sr = subst_stmt s eg.eg_sr in + let eg_fl = subst_xpath s eg.eg_fl in + let eg_fr = subst_xpath s eg.eg_fr in + let s = add_memory s eg.eg_ml eg.eg_ml in + let s = add_memory s eg.eg_mr eg.eg_mr in + let eg_pr = map_ts_inv1 (subst_form s) (eg_pr eg) in + let eg_po = map_ts_inv1 (subst_form s) (eg_po eg) in f_eagerF eg_pr eg_sl eg_fl eg_fr eg_sr eg_po | Fpr { pr_mem; pr_fun; pr_args; pr_event } -> let pr_mem = subst_mem s pr_mem in let pr_fun = subst_xpath s pr_fun in let pr_args = subst_form s pr_args in - let pr_event = - let s = add_memory s mhr mhr in - subst_form s pr_event in + let s = add_memory s pr_event.m pr_event.m in + let pr_event = map_ss_inv1 (subst_form s) pr_event in f_pr pr_mem pr_fun pr_args pr_event | Fif _ | Fint _ | Ftuple _ | Fproj _ | Fapp _ -> @@ -1102,6 +1083,20 @@ and subst_ctheory (s : subst) (cth : ctheory) = and subst_theory_source (s : subst) (ths : thsource) = { ths_base = subst_path s ths.ths_base; } +let subst_ss_inv (s : subst) (inv : ss_inv) = + let s = add_memory s inv.m inv.m in + { inv = subst_form s inv.inv; m = inv.m; } + +let subst_ts_inv (s : subst) (inv : ts_inv) = + let s = add_memory s inv.ml inv.ml in + let s = add_memory s inv.mr inv.mr in + { inv = subst_form s inv.inv; ml = inv.ml; mr = inv.mr; } + +let subst_inv (s : subst) (inv : inv) = + match inv with + | Inv_ss inv -> Inv_ss (subst_ss_inv s inv) + | Inv_ts inv -> Inv_ts (subst_ts_inv s inv) + (* -------------------------------------------------------------------- *) let init_tparams (params : (EcIdent.t * ty) list) : subst = List.fold_left (fun s (x, ty) -> add_tyvar s x ty) empty params @@ -1121,3 +1116,68 @@ let open_tydecl tyd tys = let freshen_type (tparams, ty) = let s, tparams = fresh_tparams empty tparams in (tparams, subst_ty s ty) + +(* -------------------------------------------------------------------- *) +let ss_inv_rebind ({inv;m}: ss_inv) (m': memory) : ss_inv = + if m' = m then + { inv; m } + else + let inv = subst_form (add_memory empty m m') inv in + { inv; m = m' } + +let ss_inv_generalize_as_left ({inv;m}: ss_inv) (ml: memory) (mr: memory) : ts_inv = + if ml = m then + { inv; ml; mr } + else + let s = add_memory empty m ml in + let inv = subst_form s inv in + { inv; ml; mr } + +let ss_inv_generalize_as_right ({inv;m}: ss_inv) (ml: memory) (mr: memory) : ts_inv = + if mr = m then + { inv; ml; mr } + else + let s = add_memory empty m mr in + let inv = subst_form s inv in + { inv; ml; mr } + +let f_forall_mems_ss_inv menv inv = + f_forall_mems [menv] (ss_inv_rebind inv (fst menv)).inv + +let ts_inv_rebind_left ({inv;ml;mr}: ts_inv) (m: memory) : ts_inv = + if ml = m then + { inv; ml; mr } + else + let s = add_memory empty ml m in + let inv = subst_form s inv in + { inv; ml = m; mr } + +let ts_inv_rebind_right ({inv;ml;mr}: ts_inv) (m: memory) : ts_inv = + if mr = m then + { inv; ml; mr } + else + let s = add_memory empty mr m in + let inv = subst_form s inv in + { inv; ml; mr = m } + +let ts_inv_rebind ({inv;ml;mr}: ts_inv) (ml': memory) (mr': memory) : ts_inv = + match ml' = ml, mr' = mr with + | true, true -> { inv; ml; mr } + | false, true -> ts_inv_rebind_left {inv;ml;mr} ml' + | true, false -> ts_inv_rebind_right {inv;ml;mr} mr' + | false, false -> begin let s = add_memory empty ml ml' in + let s = add_memory s mr mr' in + let inv = subst_form s inv in + { inv; ml = ml'; mr = mr' } + end + +let f_forall_mems_ts_inv menvl menvr inv = + f_forall_mems [menvl; menvr] (ts_inv_rebind inv (fst menvl) (fst menvr)).inv + +let ss_inv_forall_ml_ts_inv menvl inv = + let inv' = f_forall_mems [menvl] (ts_inv_rebind_left inv (fst menvl)).inv in + { inv=inv'; m=inv.mr} + +let ss_inv_forall_mr_ts_inv menvr inv = + let inv' = f_forall_mems [menvr] (ts_inv_rebind_right inv (fst menvr)).inv in + { inv=inv'; m=inv.ml } \ No newline at end of file diff --git a/src/ecSubst.mli b/src/ecSubst.mli index 8eabb02ae..a960d6587 100644 --- a/src/ecSubst.mli +++ b/src/ecSubst.mli @@ -74,7 +74,24 @@ val subst_stmt : subst -> stmt -> stmt val subst_progvar : subst -> prog_var -> prog_var val subst_mem : subst -> EcIdent.t -> EcIdent.t val subst_flocal : subst -> form -> form +val subst_ss_inv : subst -> ss_inv -> ss_inv +val subst_ts_inv : subst -> ts_inv -> ts_inv +val subst_inv : subst -> inv -> inv (* -------------------------------------------------------------------- *) val open_oper : operator -> ty list -> ty * operator_kind val open_tydecl : tydecl -> ty list -> ty_body + +(* -------------------------------------------------------------------- *) +val ss_inv_rebind : ss_inv -> memory -> ss_inv +val ss_inv_generalize_as_left : ss_inv -> memory -> memory -> ts_inv +val ss_inv_generalize_as_right : ss_inv -> memory -> memory -> ts_inv +val f_forall_mems_ss_inv : memenv -> ss_inv -> form + +val ts_inv_rebind : ts_inv -> memory -> memory -> ts_inv +val ts_inv_rebind_left : ts_inv -> memory -> ts_inv +val ts_inv_rebind_right : ts_inv -> memory -> ts_inv +val f_forall_mems_ts_inv : memenv -> memenv -> ts_inv -> form + +val ss_inv_forall_ml_ts_inv : memenv -> ts_inv -> ss_inv +val ss_inv_forall_mr_ts_inv : memenv -> ts_inv -> ss_inv diff --git a/src/ecTheoryReplay.ml b/src/ecTheoryReplay.ml index 0ac16191d..403a003ee 100644 --- a/src/ecTheoryReplay.ml +++ b/src/ecTheoryReplay.ml @@ -124,8 +124,8 @@ let tydecl_compatible env tyd1 tyd2 = (* -------------------------------------------------------------------- *) let expr_compatible exn env s e1 e2 = - let f1 = EcFol.form_of_expr EcFol.mhr e1 in - let f2 = EcSubst.subst_form s (EcFol.form_of_expr EcFol.mhr e2) in + let f1 = EcFol.form_of_expr e1 in + let f2 = (EcSubst.subst_form s) (EcFol.form_of_expr e2) in error_body exn (EcReduction.is_conv ~ri:ri_compatible (EcEnv.LDecl.init env []) f1 f2) let get_open_oper exn env p tys = @@ -538,7 +538,7 @@ and replay_opd (ove : _ ovrenv) (subst, ops, proofs, scope) (import, x, oopd) = | `Inline _ -> let body = try - EcFol.expr_of_form EcFol.mhr body + EcFol.expr_of_form body with EcFol.CannotTranslate -> clone_error env (CE_InlinedOpIsForm (snd ove.ovre_prefix, x)) in diff --git a/src/ecTyping.ml b/src/ecTyping.ml index 39490a68d..ccb18eaff 100644 --- a/src/ecTyping.ml +++ b/src/ecTyping.ml @@ -407,7 +407,7 @@ let gen_select_op and pvs () : OpSelect.gopsel list = let me, pvs = - match EcEnv.Memory.get_active env, actonly with + match EcEnv.Memory.get_active_ss env, actonly with | None, true -> (None, []) | me , _ -> ( me, select_pv env me name ue tvi psig) in List.map (fpv me) pvs @@ -1034,8 +1034,8 @@ let rec transty (tp : typolicy) (env : EcEnv.env) ue ty = tconstr p tyargs end | PTglob gp -> - let m,_ = trans_msymbol env gp in - EcEnv.NormMp.norm_tglob env m + let mo,_ = trans_msymbol env gp in + EcEnv.NormMp.norm_tglob env mo and transtys tp (env : EcEnv.env) ue tys = List.map (transty tp env ue) tys @@ -1593,8 +1593,9 @@ let form_of_opselect ((args @ List.map (curry f_local) xs, []), xs) in let flam = List.map (snd_map gtty) flam in - let me = odfl mhr (EcEnv.Memory.get_active env) in - let body = form_of_expr me body in + let body = match (EcEnv.Memory.get_active_ss env) with + | None -> form_of_expr body + | Some me -> (ss_inv_of_expr me body).inv in let lcmap = List.map2 (fun (x, _) y -> (x, y)) bds tosub in let subst = Fsubst.f_subst_init ~freshen:true () in let subst = @@ -1605,11 +1606,12 @@ let form_of_opselect | `Op (p, tys) -> f_op p tys ty | `Lc id -> f_local id ty | `Pv (me, pv) -> - var_or_proj (fun x ty -> f_pvar x ty (oget me)) f_proj pv ty + var_or_proj (fun x ty -> (f_pvar x ty (oget me)).inv) f_proj pv ty in (op, args) - in f_app op args codom + in + f_app op args codom (* -------------------------------------------------------------------- *) @@ -2080,7 +2082,7 @@ and transmod_body ~attop (env : EcEnv.env) x params (me:pmodule_expr) = in let memenv = fundef_add_symbol env memenv locals in - let env = EcEnv.Memory.push_active memenv env in + let env = EcEnv.Memory.push_active_ss memenv env in let locals = ref locals in let memenv = ref memenv in @@ -2210,7 +2212,7 @@ and transmod_body ~attop (env : EcEnv.env) x params (me:pmodule_expr) = | Pup_cond cup -> eval_cupdate loc env cup si in - let env = EcEnv.Memory.push_active !memenv env in + let env = EcEnv.Memory.push_active_ss !memenv env in try EcMatching.Zipper.map_range env cp change bd with @@ -2525,7 +2527,7 @@ and transbody ue memenv (env : EcEnv.env) retty pbody = (* Type-check local variables / check for dups *) let add_local memenv local = - let env = EcEnv.Memory.push_active memenv env in + let env = EcEnv.Memory.push_active_ss memenv env in let ty = local.pfl_type |> omap (transty tp_uni env ue) in let init = local.pfl_init |> omap (fst -| transexp env `InProc ue) in let ty = @@ -2562,7 +2564,7 @@ and transbody ue memenv (env : EcEnv.env) retty pbody = memenv in let memenv = List.fold_left add_local memenv pbody.pfb_locals in - let env = EcEnv.Memory.push_active memenv env in + let env = EcEnv.Memory.push_active_ss memenv env in let body = transstmt env ue pbody.pfb_body in let result = @@ -2758,7 +2760,7 @@ and transinstr (* -------------------------------------------------------------------- *) and trans_pv env { pl_desc = x; pl_loc = loc } = - let side = EcEnv.Memory.get_active env in + let side = EcEnv.Memory.get_active_ss env in match EcEnv.Var.lookup_progvar_opt ?side x env with | None -> tyerror loc env (UnknownModVar x) | Some(pv,xty) -> @@ -3028,7 +3030,7 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = let trans1 (x, s) = let mem = match s with - | None -> odfl mhr (EcEnv.Memory.get_active env) + | None -> oget (EcEnv.Memory.get_active_ss env) | Some s -> transmem env s in (transpvar env mem x, mem) in @@ -3081,11 +3083,11 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = let mp = fst (trans_msymbol env gp) in let me = - match EcEnv.Memory.current env with + match EcEnv.Memory.current_ss env with | None -> tyerror f.pl_loc env NoActiveMemory | Some me -> EcMemory.memory me in PFS.set_memused state; - EcEnv.NormMp.norm_glob env me mp + (EcEnv.NormMp.norm_glob env me mp).inv | PFint n -> f_int n @@ -3136,7 +3138,7 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = let used, aout = PFS.new_memused - (transf (EcEnv.Memory.set_active me env)) + (transf (EcEnv.Memory.set_active_ss me env)) ~force state f in if not used then begin @@ -3156,13 +3158,7 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = match EcEnv.Var.lookup_progvar_opt ~side:me (unloc x) env with | None -> tyerror x.pl_loc env (UnknownVarOrOp (unloc x, [])) | Some (x, ty) -> - var_or_proj (fun x ty -> f_pvar x ty me) f_proj x ty - in - - let check_mem loc me = - match EcEnv.Memory.byid me env with - | None -> tyerror loc env (UnknownMemName (EcIdent.name me)) - | Some _ -> () + var_or_proj (fun x ty -> (f_pvar x ty me).inv) f_proj x ty in let qual (mq : pmsymbol option) (x : pqsymbol) = @@ -3175,8 +3171,9 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = let do1 = function | GVvar x -> - let x1 = lookup EcFol.mleft (qual (om |> omap fst) x) in - let x2 = lookup EcFol.mright (qual (om |> omap snd) x) in + let ml, mr = oget (EcEnv.Memory.get_active_ts env) in + let x1 = lookup ml (qual (om |> omap fst) x) in + let x2 = lookup mr (qual (om |> omap snd) x) in unify_or_fail env ue x.pl_loc ~expct:x1.f_ty x2.f_ty; f_eq x1 x2 @@ -3201,16 +3198,15 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = List.map (fun mid -> f_glob mid mem) gl @ List.map (fun (xp, ty) -> f_pvar (EcTypes.pv_glob xp) ty mem) pv in - f_tuple res in - - let x1 = create EcFol.mleft in - let x2 = create EcFol.mright in + map_ss_inv f_tuple res in + + let ml, mr = oget (EcEnv.Memory.get_active_ts env) in + let x1 = ss_inv_generalize_right (create ml) mr in + let x2 = ss_inv_generalize_left (create mr) ml in - unify_or_fail env ue gp.pl_loc ~expct:x1.f_ty x2.f_ty; - f_eq x1 x2 + unify_or_fail env ue gp.pl_loc ~expct:x1.inv.f_ty x2.inv.f_ty; + (map_ts_inv2 f_eq x1 x2).inv in - check_mem f.pl_loc EcFol.mleft; - check_mem f.pl_loc EcFol.mright; EcFol.f_ands (List.map do1 xs) | PFeqf fs -> @@ -3225,11 +3221,11 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = and do1 (me1, me2) f = let _, f1 = PFS.new_memused - (transf (EcEnv.Memory.set_active me1 env)) + (transf (EcEnv.Memory.set_active_ss me1 env)) ~force:false state f in let _, f2 = PFS.new_memused - (transf (EcEnv.Memory.set_active me2 env)) + (transf (EcEnv.Memory.set_active_ss me2 env)) ~force:false state f in unify_or_fail env ue f.pl_loc ~expct:f1.f_ty f2.f_ty; f_eq f1 f2 @@ -3432,7 +3428,7 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = tyerror psubf.pl_loc env (AmbiguousProji (i, ty)) end - | PFprob (gp, args, m, event) -> + | PFprob (gp, args, pr_m, event) -> if mode <> `Form then tyerror f.pl_loc env (NotAnExpression `Pr); @@ -3441,10 +3437,11 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = let args,_ = transcall (fun f -> let f = transf env f in f, f.f_ty) env ue f.pl_loc fun_.f_sig args in - let memid = transmem env m in - let env = EcEnv.Fun.prF fpath env in - let event' = transf env event in - unify_or_fail env ue event.pl_loc ~expct:tbool event'.f_ty; + let memid = transmem env pr_m in + let m = EcIdent.create "&hr" in + let env = EcEnv.Fun.prF m fpath env in + let event' = {m;inv=transf env event} in + unify_or_fail env ue event.pl_loc ~expct:tbool event'.inv.f_ty; f_pr memid fpath (f_tuple args) event' | PFhoareF (pre, gp, post) -> @@ -3452,31 +3449,32 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = tyerror f.pl_loc env (NotAnExpression `Logic); let fpath = trans_gamepath env gp in - let penv, qenv = EcEnv.Fun.hoareF fpath env in + let m = EcIdent.create "&hr" in + let penv, qenv = EcEnv.Fun.hoareF m fpath env in let pre' = transf penv pre in let post' = transf qenv post in unify_or_fail penv ue pre.pl_loc ~expct:tbool pre' .f_ty; unify_or_fail qenv ue post.pl_loc ~expct:tbool post'.f_ty; - f_hoareF pre' fpath post' + f_hoareF {m;inv=pre'} fpath {m;inv=post'} | PFehoareF (pre, gp, post) -> if mode <> `Form then tyerror f.pl_loc env (NotAnExpression `Logic); - + let m = EcIdent.create "&hr" in let fpath = trans_gamepath env gp in - let penv, qenv = EcEnv.Fun.hoareF fpath env in + let penv, qenv = EcEnv.Fun.hoareF m fpath env in let pre' = transf penv pre in let post' = transf qenv post in unify_or_fail penv ue pre.pl_loc ~expct:txreal pre'.f_ty; unify_or_fail qenv ue post.pl_loc ~expct:txreal post'.f_ty; - f_eHoareF pre' fpath post' + f_eHoareF {m;inv=pre'} fpath {m;inv=post'} | PFBDhoareF (pre, gp, post, hcmp, bd) -> if mode <> `Form then tyerror f.pl_loc env (NotAnExpression `Logic); - + let m = EcIdent.create "&hr" in let fpath = trans_gamepath env gp in - let penv, qenv = EcEnv.Fun.hoareF fpath env in + let penv, qenv = EcEnv.Fun.hoareF m fpath env in let pre' = transf penv pre in let post' = transf qenv post in let bd' = transf penv bd in @@ -3484,7 +3482,7 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = unify_or_fail penv ue pre .pl_loc ~expct:tbool pre' .f_ty; unify_or_fail qenv ue post.pl_loc ~expct:tbool post'.f_ty; unify_or_fail env ue bd .pl_loc ~expct:treal bd' .f_ty; - f_bdHoareF pre' fpath post' hcmp bd' + f_bdHoareF {m;inv=pre'} fpath {m;inv=post'} hcmp {m;inv=bd'} | PFlsless gp -> if mode <> `Form then @@ -3495,30 +3493,32 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt = | PFequivF (pre, (gp1, gp2), post) -> if mode <> `Form then tyerror f.pl_loc env (NotAnExpression `Logic); - + let ml = EcIdent.create "&1" in + let mr = EcIdent.create "&2" in let fpath1 = trans_gamepath env gp1 in let fpath2 = trans_gamepath env gp2 in - let penv, qenv = EcEnv.Fun.equivF fpath1 fpath2 env in + let penv, qenv = EcEnv.Fun.equivF ml mr fpath1 fpath2 env in let pre' = transf penv pre in let post' = transf qenv post in unify_or_fail penv ue pre .pl_loc ~expct:tbool pre' .f_ty; unify_or_fail qenv ue post.pl_loc ~expct:tbool post'.f_ty; - f_equivF pre' fpath1 fpath2 post' + f_equivF {ml;mr;inv=pre'} fpath1 fpath2 {ml;mr;inv=post'} | PFeagerF (pre, (s1,gp1,gp2,s2), post) -> if mode <> `Form then tyerror f.pl_loc env (NotAnExpression `Logic); - + let ml = EcIdent.create "&1" in + let mr = EcIdent.create "&2" in let fpath1 = trans_gamepath env gp1 in let fpath2 = trans_gamepath env gp2 in - let penv, qenv = EcEnv.Fun.equivF fpath1 fpath2 env in + let penv, qenv = EcEnv.Fun.equivF ml mr fpath1 fpath2 env in let pre' = transf penv pre in let post' = transf qenv post in let s1 = transstmt env ue s1 in let s2 = transstmt env ue s2 in unify_or_fail penv ue pre .pl_loc ~expct:tbool pre' .f_ty; unify_or_fail qenv ue post.pl_loc ~expct:tbool post'.f_ty; - f_eagerF pre' s1 fpath1 fpath2 s2 post' + f_eagerF {ml;mr;inv=pre'} s1 fpath1 fpath2 s2 {ml;mr;inv=post'} and transf_r opsc env ?tt pf = let f = transf_r_tyinfo opsc env ?tt pf in @@ -3559,10 +3559,10 @@ and trans_memtype env ue (pmemtype : pmemtype) : memtype = (* -------------------------------------------------------------------- *) and transexp env ?tt mode ue { pl_desc = Expr e; pl_loc = loc; } = let f = trans_form_or_pattern env (`Expr mode) ue e tt in - let m = Option.value ~default:mhr (EcEnv.Memory.get_active env) in + let m = Option.value ~default:mhr (EcEnv.Memory.get_active_ss env) in let e = try - expr_of_form m f + expr_of_ss_inv {m;inv=f} with CannotTranslate -> (* This should not happen. *) tyerror loc env (NotAnExpression `Unknown) in diff --git a/src/ecUtils.ml b/src/ecUtils.ml index 6213d2f96..e852ce0c0 100644 --- a/src/ecUtils.ml +++ b/src/ecUtils.ml @@ -175,6 +175,8 @@ let pair_equal tx ty (x1, y1) (x2, y2) = let swap (x, y) = (y, x) +let flip f x y = f y x + (* -------------------------------------------------------------------- *) module Option = BatOption diff --git a/src/ecUtils.mli b/src/ecUtils.mli index fe135ee60..7d0a4c3c8 100644 --- a/src/ecUtils.mli +++ b/src/ecUtils.mli @@ -99,6 +99,8 @@ val snd_map : ('b -> 'c) -> 'a * 'b -> 'a * 'c val swap: 'a * 'b -> 'b * 'a +val flip: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c + (* -------------------------------------------------------------------- *) type 'a eq = 'a -> 'a -> bool type 'a cmp = 'a -> 'a -> int diff --git a/src/phl/ecPhlApp.ml b/src/phl/ecPhlApp.ml index 554aa2402..7f3f160a5 100644 --- a/src/phl/ecPhlApp.ml +++ b/src/phl/ecPhlApp.ml @@ -3,8 +3,9 @@ open EcUtils open EcLocation open EcParsetree open EcTypes -open EcModules open EcFol +open EcAst +open EcSubst open EcCoreGoal open EcLowGoal @@ -17,8 +18,8 @@ let t_hoare_app_r i phi tc = let env = FApi.tc1_env tc in let hs = tc1_as_hoareS tc in let s1, s2 = s_split env i hs.hs_s in - let a = f_hoareS_r { hs with hs_s = stmt s1; hs_po = phi } in - let b = f_hoareS_r { hs with hs_pr = phi; hs_s = stmt s2 } in + let a = f_hoareS (snd hs.hs_m) (hs_pr hs) (stmt s1) phi in + let b = f_hoareS (snd hs.hs_m) phi (stmt s2) (hs_po hs) in FApi.xmutate1 tc `HlApp [a; b] let t_hoare_app = FApi.t_low2 "hoare-app" t_hoare_app_r @@ -28,8 +29,8 @@ let t_ehoare_app_r i f tc = let env = FApi.tc1_env tc in let hs = tc1_as_ehoareS tc in let s1, s2 = s_split env i hs.ehs_s in - let a = f_eHoareS_r { hs with ehs_s = stmt s1; ehs_po = f } in - let b = f_eHoareS_r { hs with ehs_pr = f; ehs_s = stmt s2 } in + let a = f_eHoareS (snd hs.ehs_m) (ehs_pr hs) (stmt s1) f in + let b = f_eHoareS (snd hs.ehs_m) f (stmt s2) (ehs_po hs) in FApi.xmutate1 tc `HlApp [a; b] let t_ehoare_app = FApi.t_low2 "hoare-app" t_ehoare_app_r @@ -38,43 +39,50 @@ let t_ehoare_app = FApi.t_low2 "hoare-app" t_ehoare_app_r let t_bdhoare_app_r_low i (phi, pR, f1, f2, g1, g2) tc = let env = FApi.tc1_env tc in let bhs = tc1_as_bdhoareS tc in + let m = fst bhs.bhs_m in + let phi = ss_inv_rebind phi m in + let pR = ss_inv_rebind pR m in + let f1 = ss_inv_rebind f1 m in + let f2 = ss_inv_rebind f2 m in + let g1 = ss_inv_rebind g1 m in + let g2 = ss_inv_rebind g2 m in let s1, s2 = s_split env i bhs.bhs_s in let s1, s2 = stmt s1, stmt s2 in - let nR = f_not pR in - let cond_phi = f_hoareS bhs.bhs_m bhs.bhs_pr s1 phi in - let condf1 = f_bdHoareS_r { bhs with bhs_s = s1; bhs_po = pR; bhs_bd = f1; } in - let condg1 = f_bdHoareS_r { bhs with bhs_s = s1; bhs_po = nR; bhs_bd = g1; } in - let condf2 = f_bdHoareS_r - { bhs with bhs_s = s2; bhs_pr = f_and_simpl phi pR; bhs_bd = f2; } in - let condg2 = f_bdHoareS_r - { bhs with bhs_s = s2; bhs_pr = f_and_simpl phi nR; bhs_bd = g2; } in + let nR = map_ss_inv1 f_not pR in + let mt = snd bhs.bhs_m in + let cond_phi = f_hoareS mt (bhs_pr bhs) s1 phi in + let condf1 = f_bdHoareS mt (bhs_pr bhs) s1 pR bhs.bhs_cmp f1 in + let condg1 = f_bdHoareS mt (bhs_pr bhs) s1 nR bhs.bhs_cmp g1 in + let condf2 = f_bdHoareS mt (map_ss_inv2 f_and_simpl phi pR) s2 (bhs_po bhs) bhs.bhs_cmp f2 in + let condg2 = f_bdHoareS mt (map_ss_inv2 f_and_simpl phi nR) s2 (bhs_po bhs) bhs.bhs_cmp g2 in let bd = - (f_real_add_simpl (f_real_mul_simpl f1 f2) (f_real_mul_simpl g1 g2)) in + (map_ss_inv2 f_real_add_simpl (map_ss_inv2 f_real_mul_simpl f1 f2) (map_ss_inv2 f_real_mul_simpl g1 g2)) in let condbd = match bhs.bhs_cmp with - | FHle -> f_real_le bd bhs.bhs_bd - | FHeq -> f_eq bd bhs.bhs_bd - | FHge -> f_real_le bhs.bhs_bd bd in - let condbd = f_imp bhs.bhs_pr condbd in + | FHle -> map_ss_inv2 f_real_le bd (bhs_bd bhs) + | FHeq -> map_ss_inv2 f_eq bd (bhs_bd bhs) + | FHge -> map_ss_inv2 f_real_le (bhs_bd bhs) bd in + let condbd = map_ss_inv2 f_imp (bhs_pr bhs) condbd in let (ir1, ir2) = EcIdent.create "r", EcIdent.create "r" in let (r1 , r2 ) = f_local ir1 treal, f_local ir2 treal in let condnm = - let eqs = f_and (f_eq f2 r1) (f_eq g2 r2) in + let eqs = map_ss_inv2 f_and (map_ss_inv1 ((EcUtils.flip f_eq) r1) f2) + (map_ss_inv1 ((EcUtils.flip f_eq) r2) g2) in f_forall [(ir1, GTty treal); (ir2, GTty treal)] - (f_hoareS bhs.bhs_m (f_and bhs.bhs_pr eqs) s1 eqs) in - let conds = [f_forall_mems [bhs.bhs_m] condbd; condnm] in + (f_hoareS (snd bhs.bhs_m) (map_ss_inv2 f_and (bhs_pr bhs) eqs) s1 eqs) in + let conds = [EcSubst.f_forall_mems_ss_inv bhs.bhs_m condbd; condnm] in let conds = - if f_equal g1 f_r0 + if f_equal g1.inv f_r0 then condg1 :: conds - else if f_equal g2 f_r0 + else if f_equal g2.inv f_r0 then condg2 :: conds else condg1 :: condg2 :: conds in let conds = - if f_equal f1 f_r0 + if f_equal f1.inv f_r0 then condf1 :: conds - else if f_equal f2 f_r0 + else if f_equal f2.inv f_r0 then condf2 :: conds else condf1 :: condf2 :: conds in @@ -86,7 +94,7 @@ let t_bdhoare_app_r_low i (phi, pR, f1, f2, g1, g2) tc = let t_bdhoare_app_r i info tc = let tactic tc = let hs = tc1_as_hoareS tc in - let tt1 = EcPhlConseq.t_hoareS_conseq_nm hs.hs_pr f_true in + let tt1 = EcPhlConseq.t_hoareS_conseq_nm (hs_pr hs) {m=(fst hs.hs_m);inv=f_true} in let tt2 = EcPhlAuto.t_pl_trivial in FApi.t_seqs [tt1; tt2; t_fail] tc in @@ -103,19 +111,28 @@ let t_equiv_app (i, j) phi tc = let es = tc1_as_equivS tc in let sl1,sl2 = s_split env i es.es_sl in let sr1,sr2 = s_split env j es.es_sr in - let a = f_equivS_r {es with es_sl=stmt sl1; es_sr=stmt sr1; es_po=phi} in - let b = f_equivS_r {es with es_pr=phi; es_sl=stmt sl2; es_sr=stmt sr2} in + let mtl, mtr = snd es.es_ml, snd es.es_mr in + let a = f_equivS mtl mtr (es_pr es) (stmt sl1) (stmt sr1) phi in + let b = f_equivS mtl mtr phi (stmt sl2) (stmt sr2) (es_po es) in FApi.xmutate1 tc `HlApp [a; b] let t_equiv_app_onesided side i pre post tc = let env = FApi.tc1_env tc in let es = tc1_as_equivS tc in - let m, s, s' = + let (ml, mr) = fst es.es_ml, fst es.es_mr in + let s, s', p', q' = match side with - | `Left -> es.es_ml, es.es_sl, es.es_sr - | `Right -> es.es_mr, es.es_sr, es.es_sl + | `Left -> + let p' = ss_inv_generalize_right (EcSubst.ss_inv_rebind pre ml) mr in + let q' = ss_inv_generalize_right (EcSubst.ss_inv_rebind post ml) mr in + es.es_sl, es.es_sr, p', q' + | `Right -> + let p' = ss_inv_generalize_left (EcSubst.ss_inv_rebind pre mr) ml in + let q' = ss_inv_generalize_left (EcSubst.ss_inv_rebind post mr) ml in + es.es_sr, es.es_sl, p', q' in + let generalize_mod_side= sideif side generalize_mod_left generalize_mod_right in let ij = match side with | `Left -> (i, Zpr.cpos (List.length s'. s_node)) @@ -123,9 +140,7 @@ let t_equiv_app_onesided side i pre post tc = let _s1, s2 = s_split env i s in let modi = EcPV.s_write env (EcModules.stmt s2) in - let subst = Fsubst.f_subst_mem mhr (fst m) in - let p' = subst pre and q' = subst post in - let r = f_and p' (generalize_mod env (fst m) modi (f_imp q' es.es_po)) in + let r = map_ts_inv2 f_and p' (generalize_mod_side env modi (map_ts_inv2 f_imp q' (es_po es))) in FApi.t_seqsub (t_equiv_app ij r) [t_id; (* s1 ~ s' : pr ==> r *) FApi.t_seqsub (EcPhlConseq.t_equivS_conseq_nm p' q') @@ -140,28 +155,32 @@ let process_phl_bd_info dir bd_info tc = match bd_info with | PAppNone -> let hs = tc1_as_bdhoareS tc in + let m = fst hs.bhs_m in let f1, f2 = match dir with - | Backs -> hs.bhs_bd, f_r1 - | Fwds -> f_r1, hs.bhs_bd + | Backs -> bhs_bd hs, {m;inv=f_r1} + | Fwds -> {m;inv=f_r1}, bhs_bd hs in (* The last argument will not be used *) - (f_true, f1, f2, f_r0, f_r1) + ({m;inv=f_true}, f1, f2, {m;inv=f_r0}, {m;inv=f_r1}) | PAppSingle f -> let hs = tc1_as_bdhoareS tc in + let m = fst hs.bhs_m in let f = snd (TTC.tc1_process_Xhl_form tc treal f) in let f1, f2 = match dir with - | Backs -> (f_real_div hs.bhs_bd f, f) - | Fwds -> (f, f_real_div hs.bhs_bd f) + | Backs -> (map_ss_inv2 f_real_div (bhs_bd hs) f, f) + | Fwds -> (f, map_ss_inv2 f_real_div (bhs_bd hs) f) in - (f_true, f1, f2, f_r0, f_r1) + ({m;inv=f_true}, f1, f2, {m;inv=f_r0}, {m;inv=f_r1}) | PAppMult (phi, f1, f2, g1, g2) -> + let hs = tc1_as_bdhoareS tc in + let m = fst hs.bhs_m in let phi = phi |> omap (fun f -> snd (TTC.tc1_process_Xhl_formula tc f)) - |> odfl f_true in + |> odfl {m;inv=f_true} in let check_0 f = if not (f_equal f f_r0) then @@ -173,11 +192,11 @@ let process_phl_bd_info dir bd_info tc = | Some fp, None -> let _, f = TTC.tc1_process_Xhl_form tc treal fp in - reloc fp.pl_loc check_0 f; (f, f_r1) + reloc fp.pl_loc check_0 f.inv; (f, {m;inv=f_r1}) | None, Some fp -> let _, f = TTC.tc1_process_Xhl_form tc treal fp in - reloc fp.pl_loc check_0 f; (f_r1, f) + reloc fp.pl_loc check_0 f.inv; ({m;inv=f_r1}, f) | Some f1, Some f2 -> let _, f1 = TTC.tc1_process_Xhl_form tc treal f1 in diff --git a/src/phl/ecPhlApp.mli b/src/phl/ecPhlApp.mli index 2036ee667..41d089476 100644 --- a/src/phl/ecPhlApp.mli +++ b/src/phl/ecPhlApp.mli @@ -1,16 +1,16 @@ (* -------------------------------------------------------------------- *) open EcUtils open EcParsetree -open EcFol open EcCoreGoal.FApi open EcMatching.Position +open EcAst (* -------------------------------------------------------------------- *) -val t_hoare_app : codepos1 -> form -> backward -val t_ehoare_app : codepos1 -> form -> backward -val t_bdhoare_app : codepos1 -> form tuple6 -> backward -val t_equiv_app : codepos1 pair -> form -> backward -val t_equiv_app_onesided : side -> codepos1 -> form -> form -> backward +val t_hoare_app : codepos1 -> ss_inv -> backward +val t_ehoare_app : codepos1 -> ss_inv -> backward +val t_bdhoare_app : codepos1 -> ss_inv tuple6 -> backward +val t_equiv_app : codepos1 pair -> ts_inv -> backward +val t_equiv_app_onesided : side -> codepos1 -> ss_inv -> ss_inv -> backward (* -------------------------------------------------------------------- *) val process_app : app_info -> backward diff --git a/src/phl/ecPhlAuto.ml b/src/phl/ecPhlAuto.ml index 6a28e3b33..0970d5646 100644 --- a/src/phl/ecPhlAuto.ml +++ b/src/phl/ecPhlAuto.ml @@ -2,6 +2,7 @@ open EcUtils open EcFol open EcModules +open EcAst open EcCoreGoal open EcLowGoal @@ -18,15 +19,15 @@ let t_exfalso_r tc = FApi.t_or EcPhlTAuto.t_core_exfalso (FApi.t_seqsub - (EcPhlConseq.t_conseq f_false post) + (EcPhlConseq.t_conseq (map_inv1 (fun _ -> f_false) post) post) [t_id; t_trivial; EcPhlTAuto.t_core_exfalso]) tc let t_exfalso = FApi.t_low0 "exfalso" t_exfalso_r (* -------------------------------------------------------------------- *) -let prnd_info = - EcParsetree.PSingleRndParam f_predT +let prnd_info m = + EcParsetree.PSingleRndParam (fun ty -> {m;inv=f_predT ty}) (* -------------------------------------------------------------------- *) let t_auto_rnd_hoare_r tc = @@ -37,7 +38,7 @@ let t_auto_rnd_bdhoare_r tc = let hs = tc1_as_bdhoareS tc in match List.olast hs.bhs_s.s_node with - | Some { i_node = Srnd _ } -> EcPhlRnd.t_bdhoare_rnd prnd_info tc + | Some { i_node = Srnd _ } -> EcPhlRnd.t_bdhoare_rnd (prnd_info (fst hs.bhs_m)) tc | _ -> tc_noauto_error !!tc () (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlBdHoare.ml b/src/phl/ecPhlBdHoare.ml index f7921ade1..fa5fa5201 100644 --- a/src/phl/ecPhlBdHoare.ml +++ b/src/phl/ecPhlBdHoare.ml @@ -18,20 +18,20 @@ let t_hoare_bd_hoare tc = match concl.f_node with | FbdHoareF bhf -> - if bhf.bhf_cmp = FHeq && f_equal bhf.bhf_bd f_r0 + if bhf.bhf_cmp = FHeq && f_equal (bhf_bd bhf).inv f_r0 then t_hoare_of_bdhoareF tc else FApi.t_seqsub - (t_bdHoareF_conseq_bd FHeq f_r0) + (t_bdHoareF_conseq_bd FHeq {m=bhf.bhf_m; inv=f_r0}) [FApi.t_try EcPhlAuto.t_pl_trivial; t_hoare_of_bdhoareF] tc | FbdHoareS bhs -> - if bhs.bhs_cmp = FHeq && f_equal bhs.bhs_bd f_r0 + if bhs.bhs_cmp = FHeq && f_equal (bhs_bd bhs).inv f_r0 then t_hoare_of_bdhoareS tc else FApi.t_seqsub - (t_bdHoareS_conseq_bd FHeq f_r0) + (t_bdHoareS_conseq_bd FHeq {m=fst bhs.bhs_m; inv=f_r0}) [FApi.t_try EcPhlAuto.t_pl_trivial; t_hoare_of_bdhoareS] tc @@ -42,13 +42,13 @@ let t_hoare_bd_hoare tc = (* -------------------------------------------------------------------- *) type 'a split_t = { - as_bdh : proofenv -> form -> 'a * form * hoarecmp * form; - mk_bdh : 'a * form * hoarecmp * form -> form; + as_bdh : proofenv -> form -> 'a * ss_inv * hoarecmp * ss_inv; + mk_bdh : 'a * ss_inv * hoarecmp * ss_inv -> form; } type 'a destr_t = { - as_bop : proofenv -> form -> form * form; - mk_bop : form -> form -> form; + as_bop : proofenv -> ss_inv -> ss_inv * ss_inv; + mk_bop : ss_inv -> ss_inv -> ss_inv; } (* -------------------------------------------------------------------- *) @@ -60,19 +60,19 @@ let t_bdhoare_split_bop sp dt b1 b2 b3 tc = let g1 = sp.mk_bdh (bh, a, cmp, b1) in let g2 = sp.mk_bdh (bh, b, cmp, b2) in let g3 = sp.mk_bdh (bh, dt.mk_bop a b, hoarecmp_opp cmp, b3) in - let nb = f_real_sub (f_real_add b1 b2) b3 in + let nb = map_ss_inv2 f_real_sub (map_ss_inv2 f_real_add b1 b2) b3 in - assert (f_equal nb bd); + assert (f_equal nb.inv bd.inv); FApi.xmutate1 tc `BdHoareSplit [g1; g2; g3] (* -------------------------------------------------------------------- *) let t_bdhoare_split_bop_conseq t_conseq_bd sp dt b1 b2 b3 tc = let concl = FApi.tc1_goal tc in let _, _, cmp, b = sp.as_bdh !!tc concl in - let nb = f_real_sub (f_real_add b1 b2) b3 in + let nb = map_ss_inv2 f_real_sub (map_ss_inv2 f_real_add b1 b2) b3 in let t_main = t_bdhoare_split_bop sp dt b1 b2 b3 in - if f_equal nb b + if f_equal nb.inv b.inv then t_main tc else FApi.t_seqsub (t_conseq_bd cmp nb) [t_id; t_main] tc @@ -87,10 +87,10 @@ let bdhoare_kind tc = let gen_S tactic = let as_bdh pf f = let bh = pf_as_bdhoareS pf f in - (bh, bh.bhs_po, bh.bhs_cmp, bh.bhs_bd) + (bh, (bhs_po bh), bh.bhs_cmp, bhs_bd bh) and mk_bdh (bh, po, cmp, b) = - f_bdHoareS_r { bh with bhs_po = po; bhs_cmp = cmp; bhs_bd = b; } in + f_bdHoareS (snd bh.bhs_m) (bhs_pr bh) bh.bhs_s po cmp b in tactic t_bdHoareS_conseq_bd { as_bdh; mk_bdh; } @@ -98,21 +98,24 @@ let gen_S tactic = let gen_F tactic = let as_bdh pf f = let bh = pf_as_bdhoareF pf f in - (bh, bh.bhf_po, bh.bhf_cmp, bh.bhf_bd) + (bh, (bhf_po bh), bh.bhf_cmp, bhf_bd bh) in - and mk_bdh (bh, po, cmp, b) = - f_bdHoareF bh.bhf_pr bh.bhf_f po cmp b in + let mk_bdh (bh, po, cmp, b) = + f_bdHoareF (bhf_pr bh) bh.bhf_f po cmp b in tactic t_bdHoareF_conseq_bd { as_bdh; mk_bdh; } (* -------------------------------------------------------------------- *) let and_dt = let destr_and pf f = - try destr_and f + try + let f1 = map_ss_inv1 (fun f -> fst (destr_and f)) f in + let f2 = map_ss_inv1 (fun f -> snd (destr_and f)) f in + (f1, f2) with DestrError _ -> tc_error pf "the postcondition must be a conjunction" in - { as_bop = destr_and; mk_bop = f_or; } + { as_bop = destr_and; mk_bop = map_ss_inv2 f_or; } let t_bdhoareS_and = gen_S t_bdhoare_split_bop_conseq and_dt let t_bdhoareF_and = gen_F t_bdhoare_split_bop_conseq and_dt @@ -125,11 +128,14 @@ let t_bdhoare_and b1 b2 b3 tc = (* -------------------------------------------------------------------- *) let or_dt = let destr_or pf f = - try destr_or f + try + let f1 = map_ss_inv1 (fun f -> fst (destr_or f)) f in + let f2 = map_ss_inv1 (fun f -> snd (destr_or f)) f in + (f1, f2) with DestrError _ -> tc_error pf "the postcondition must be a disjunction" in - { as_bop = destr_or; mk_bop = f_and; } + { as_bop = destr_or; mk_bop = map_ss_inv2 f_and; } let t_bdhoareS_or = gen_S t_bdhoare_split_bop_conseq or_dt let t_bdhoareF_or = gen_F t_bdhoare_split_bop_conseq or_dt @@ -142,19 +148,20 @@ let t_bdhoare_or b1 b2 b3 tc = (* -------------------------------------------------------------------- *) let t_bdhoare_split_not split b1 b2 tc = let bh, po, cmp, bd = split.as_bdh !!tc (FApi.tc1_goal tc) in - let g1 = split.mk_bdh (bh, f_true, cmp, b1) in - let g2 = split.mk_bdh (bh, f_not_simpl po, hoarecmp_opp cmp, b2) in - let nb = f_real_sub b1 b2 in + let g1 = split.mk_bdh (bh, map_ss_inv1 (fun _ -> f_true) po, cmp, b1) in + let g2 = split.mk_bdh (bh, map_ss_inv1 f_not_simpl po, hoarecmp_opp cmp, b2) in + let nb = map_ss_inv2 f_real_sub b1 b2 in - assert (f_equal nb bd); + assert (f_equal nb.inv bd.inv); FApi.xmutate1 tc `BdHoareSplit [g1; g2] let t_bdhoare_split_not_conseq t_conseq_bd split b1 b2 tc = + let hyps = FApi.tc1_hyps tc in let _, _, cmp, b = split.as_bdh !!tc (FApi.tc1_goal tc) in - let nb = f_real_sub b1 b2 in + let nb = map_ss_inv2 f_real_sub b1 b2 in let t_main = t_bdhoare_split_not split b1 b2 in - if f_equal nb b + if EcReduction.ss_inv_alpha_eq hyps nb b then t_main tc else FApi.t_seqsub (t_conseq_bd cmp nb) [t_id; t_main] tc diff --git a/src/phl/ecPhlBdHoare.mli b/src/phl/ecPhlBdHoare.mli index f12652003..691d592bb 100644 --- a/src/phl/ecPhlBdHoare.mli +++ b/src/phl/ecPhlBdHoare.mli @@ -1,9 +1,9 @@ (* -------------------------------------------------------------------- *) -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) -val t_bdhoare_and : form -> form -> form -> backward -val t_bdhoare_or : form -> form -> form -> backward -val t_bdhoare_not : form -> form -> backward +val t_bdhoare_and : ss_inv -> ss_inv -> ss_inv -> backward +val t_bdhoare_or : ss_inv -> ss_inv -> ss_inv -> backward +val t_bdhoare_not : ss_inv -> ss_inv -> backward val t_hoare_bd_hoare : backward diff --git a/src/phl/ecPhlCall.ml b/src/phl/ecPhlCall.ml index f2f43747d..24cdb6794 100644 --- a/src/phl/ecPhlCall.ml +++ b/src/phl/ecPhlCall.ml @@ -7,6 +7,7 @@ open EcModules open EcFol open EcEnv open EcPV +open EcSubst open EcCoreGoal open EcLowGoal @@ -16,44 +17,46 @@ module PT = EcProofTerm module TTC = EcProofTyping (* -------------------------------------------------------------------- *) -let wp_asgn_call env m lv res post = +let wp_asgn_call env lv res post = + assert (res.m = post.m); + let m = post.m in match lv with | None -> post | Some lv -> - let lets = lv_subst m lv res in - mk_let_of_lv_substs env ([lets], post) + let lets = lv_subst m lv res.inv in + {m;inv=mk_let_of_lv_substs env ([lets], post.inv)} let subst_args_call env m e s = - PVM.add env pv_arg m (form_of_expr m e) s + PVM.add env pv_arg m (ss_inv_of_expr m e).inv s (* -------------------------------------------------------------------- *) let wp2_call - env fpre fpost (lpl,fl,argsl) modil (lpr,fr,argsr) modir ml mr post hyps + env fpre fpost (lpl,fl,argsl) modil (lpr,fr,argsr) modir post hyps = + let ml, mr = post.ml, post.mr in let fsigl = (Fun.by_xpath fl env).f_sig in let fsigr = (Fun.by_xpath fr env).f_sig in (* The wp *) let pvresl = pv_res and pvresr = pv_res in let vresl = LDecl.fresh_id hyps "result_L" in let vresr = LDecl.fresh_id hyps "result_R" in - let fresl = f_local vresl fsigl.fs_ret in - let fresr = f_local vresr fsigr.fs_ret in - let post = wp_asgn_call env ml lpl fresl post in - let post = wp_asgn_call env mr lpr fresr post in + let fresl = {ml;mr; inv=f_local vresl fsigl.fs_ret} in + let fresr = {ml;mr; inv=f_local vresr fsigr.fs_ret} in + let post = map_ts_inv_left2 (wp_asgn_call env lpl) fresl post in + let post = map_ts_inv_right2 (wp_asgn_call env lpr) fresr post in let s = PVM.empty in - let s = PVM.add env pvresr mr fresr s in - let s = PVM.add env pvresl ml fresl s in - let fpost = PVM.subst env s fpost in - let post = generalize_mod env mr modir (f_imp_simpl fpost post) in - let post = generalize_mod env ml modil post in - let post = - f_forall_simpl + let s = PVM.add env pvresr mr fresr.inv s in + let s = PVM.add env pvresl ml fresl.inv s in + let fpost = map_ts_inv1 (PVM.subst env s) fpost in + let post = generalize_mod_ts_inv env modil modir (map_ts_inv2 f_imp_simpl fpost post) in + let post = map_ts_inv1 + (f_forall_simpl [(vresl, GTty fsigl.fs_ret); - (vresr, GTty fsigr.fs_ret)] + (vresr, GTty fsigr.fs_ret)]) post in let spre = subst_args_call env ml (e_tuple argsl) PVM.empty in let spre = subst_args_call env mr (e_tuple argsr) spre in - f_anda_simpl (PVM.subst env spre fpre) post + map_ts_inv2 f_anda_simpl (map_ts_inv1 (PVM.subst env spre) fpre) post (* -------------------------------------------------------------------- *) let t_hoare_call fpre fpost tc = @@ -64,18 +67,21 @@ let t_hoare_call fpre fpost tc = let fsig = (Fun.by_xpath f env).f_sig in (* The function satisfies the specification *) let f_concl = f_hoareF fpre f fpost in + (* substitute memories *) + let fpre = (ss_inv_rebind fpre m) in + let fpost = (ss_inv_rebind fpost m) in (* The wp *) let pvres = pv_res in let vres = EcIdent.create "result" in - let fres = f_local vres fsig.fs_ret in - let post = wp_asgn_call env m lp fres hs.hs_po in - let fpost = PVM.subst1 env pvres m fres fpost in + let fres = {m;inv=f_local vres fsig.fs_ret} in + let post = wp_asgn_call env lp fres (hs_po hs) in + let fpost = map_ss_inv2 (PVM.subst1 env pvres m) fres fpost in let modi = f_write env f in - let post = generalize_mod env m modi (f_imp_simpl fpost post) in - let post = f_forall_simpl [(vres, GTty fsig.fs_ret)] post in + let post = generalize_mod_ss_inv env modi (map_ss_inv2 f_imp_simpl fpost post) in + let post = map_ss_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) post in let spre = subst_args_call env m (e_tuple args) PVM.empty in - let post = f_anda_simpl (PVM.subst env spre fpre) post in - let concl = f_hoareS_r { hs with hs_s = s; hs_po=post} in + let post = map_ss_inv2 f_anda_simpl (map_ss_inv1 (PVM.subst env spre) fpre) post in + let concl = f_hoareS (snd hs.hs_m) (hs_pr hs) s post in FApi.xmutate1 tc `HlCall [f_concl; concl] @@ -86,6 +92,8 @@ let ehoare_call_pre_post fpre fpost tc = let hs = tc1_as_ehoareS tc in let (lp,f,args),s = tc1_last_call tc hs.ehs_s in let m = EcMemory.memory hs.ehs_m in + let fpre = ss_inv_rebind fpre m in + let fpost = ss_inv_rebind fpost m in (* Ensure that all asigned variables are locals *) let all_loc = match lp with @@ -99,17 +107,17 @@ let ehoare_call_pre_post fpre fpost tc = match lp with | None -> None | Some (LvVar (v,ty)) -> Some (f_pvar v ty m) - | Some (LvTuple vs) -> Some (f_tuple (List.map (fun (v,ty) -> f_pvar v ty m) vs)) in + | Some (LvTuple vs) -> Some (map_ss_inv f_tuple (List.map (fun (v,ty) -> f_pvar v ty m) vs)) in let pvres = pv_res in let wppost = - omap_dfl (fun fres -> PVM.subst1 env pvres m fres fpost) fpost fres in - let fv = PV.fv env m wppost in + omap_dfl (fun fres -> map_ss_inv2 (PVM.subst1 env pvres m) fres fpost) fpost fres in + let fv = PV.fv env m wppost.inv in if PV.mem_pv env pv_res fv then tc_error !!tc "ehoare call core rule: the post condition of the function depend on res but the result is not assigned"; let spre = subst_args_call env m (e_tuple args) PVM.empty in - let wppre = PVM.subst env spre fpre in + let wppre = map_ss_inv1 (PVM.subst env spre) fpre in hyps, env, hs, s, f, wppre, wppost @@ -117,17 +125,17 @@ let t_ehoare_call_core fpre fpost tc = let hyps, env, hs, s, f, wppre, wppost = ehoare_call_pre_post fpre fpost tc in if not (List.is_empty s.s_node) then tc_error !!tc "ehoare call core rule: only single call statements are accepted"; - if not (EcReduction.is_conv hyps hs.ehs_po wppost) then - (let env = EcEnv.Memory.push_active hs.ehs_m env in + if not (EcReduction.ss_inv_alpha_eq hyps (ehs_po hs) wppost) then + (let env = EcEnv.Memory.push_active_ss hs.ehs_m env in let ppe = EcPrinting.PPEnv.ofenv env in tc_error !!tc "ehoare call core rule: wrong post-condition %a instead %a" - (EcPrinting.pp_form ppe) hs.ehs_po (EcPrinting.pp_form ppe) wppost); + (EcPrinting.pp_form ppe) (ehs_po hs).inv (EcPrinting.pp_form ppe) wppost.inv); - if not (EcReduction.is_conv hyps hs.ehs_pr wppre) then - (let env = EcEnv.Memory.push_active hs.ehs_m env in + if not (EcReduction.ss_inv_alpha_eq hyps (ehs_pr hs) wppre) then + (let env = EcEnv.Memory.push_active_ss hs.ehs_m env in let ppe = EcPrinting.PPEnv.ofenv env in tc_error !!tc "ehoare call core rule: wrong pre-condition %a instead %a" - (EcPrinting.pp_form ppe) hs.ehs_pr (EcPrinting.pp_form ppe) wppre); + (EcPrinting.pp_form ppe) (ehs_pr hs).inv (EcPrinting.pp_form ppe) wppre.inv); (* The function satisfies the specification *) let f_concl = f_eHoareF fpre f fpost in @@ -144,7 +152,8 @@ let t_ehoare_call fpre fpost tc = let t_ehoare_call_concave f fpre fpost tc = let _, _, _, s, _, wppre, wppost = ehoare_call_pre_post fpre fpost tc in let tcenv = - EcPhlApp.t_ehoare_app (EcMatching.Zipper.cpos (List.length s.s_node)) (f_app_simpl f [wppre] txreal) tc in + EcPhlApp.t_ehoare_app (EcMatching.Zipper.cpos (List.length s.s_node)) + (map_ss_inv2 (fun wppre f -> f_app_simpl f [wppre] txreal) wppre f) tc in let tcenv = FApi.t_swap_goals 0 1 tcenv in let t_call = FApi.t_seqsub (EcPhlConseq.t_ehoareS_concave f wppre wppost) @@ -174,52 +183,55 @@ let t_bdhoare_call fpre fpost opt_bd tc = let env = FApi.tc1_env tc in let bhs = tc1_as_bdhoareS tc in let (lp,f,args),s = tc1_last_call tc bhs.bhs_s in - let m = EcMemory.memory bhs.bhs_m in + let m = fpre.m in let fsig = (Fun.by_xpath f env).f_sig in + let bhs_bd = ss_inv_rebind (bhs_bd bhs) m in + let bhs_po = ss_inv_rebind (bhs_po bhs) m in + let bhs_pr = ss_inv_rebind (bhs_pr bhs) m in + + (* The function satisfies the specification *) let f_concl = - bdhoare_call_spec !!tc fpre fpost f bhs.bhs_cmp bhs.bhs_bd opt_bd in + bdhoare_call_spec !!tc fpre fpost f bhs.bhs_cmp bhs_bd opt_bd in (* The wp *) let pvres = pv_res in let vres = EcIdent.create "result" in - let fres = f_local vres fsig.fs_ret in - let post = wp_asgn_call env m lp fres bhs.bhs_po in - let fpost = PVM.subst1 env pvres m fres fpost in + let fres = {m;inv=f_local vres fsig.fs_ret} in + let post = wp_asgn_call env lp fres bhs_po in + let fpost = map_ss_inv2 (PVM.subst1 env pvres m) fres fpost in let modi = f_write env f in let post = match bhs.bhs_cmp with - | FHle -> f_imp_simpl post fpost - | FHge -> f_imp_simpl fpost post + | FHle -> map_ss_inv2 f_imp_simpl post fpost + | FHge -> map_ss_inv2 f_imp_simpl fpost post | FHeq when f_equal bhs.bhs_bd f_r0 -> - f_imp_simpl post fpost + map_ss_inv2 f_imp_simpl post fpost | FHeq when f_equal bhs.bhs_bd f_r1 -> - f_imp_simpl fpost post + map_ss_inv2 f_imp_simpl fpost post - | FHeq -> f_iff_simpl fpost post in + | FHeq -> map_ss_inv2 f_iff_simpl fpost post in - let post = generalize_mod env m modi post in - let post = f_forall_simpl [(vres, GTty fsig.fs_ret)] post in + let post = generalize_mod_ss_inv env modi post in + let post = map_ss_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) post in let spre = subst_args_call env m (e_tuple args) PVM.empty in - let post = f_anda_simpl (PVM.subst env spre fpre) post in + let post = map_ss_inv2 f_anda_simpl (map_ss_inv1 (PVM.subst env spre) fpre) post in (* most of the above code is duplicated from t_hoare_call *) - let concl = match bhs.bhs_cmp, opt_bd with + let concl = + let _,mt = bhs.bhs_m in + match bhs.bhs_cmp, opt_bd with | FHle, None -> - f_hoareS bhs.bhs_m bhs.bhs_pr s post + f_hoareS mt bhs_pr s post | FHeq, Some bd -> - f_bdHoareS_r { bhs with - bhs_s = s; bhs_po = post; bhs_bd = f_real_div bhs.bhs_bd bd; } + f_bdHoareS mt bhs_pr s post bhs.bhs_cmp (map_ss_inv2 f_real_div bhs_bd bd) | FHeq, None -> - f_bdHoareS_r { bhs with - bhs_s = s; bhs_po = post; bhs_bd = f_r1; } + f_bdHoareS mt bhs_pr s post bhs.bhs_cmp {m;inv=f_r1} | FHge, Some bd -> - f_bdHoareS_r { bhs with - bhs_s = s; bhs_po = post; bhs_bd = f_real_div bhs.bhs_bd bd; } + f_bdHoareS mt bhs_pr s post bhs.bhs_cmp (map_ss_inv2 f_real_div bhs_bd bd) | FHge, None -> - f_bdHoareS_r { bhs with - bhs_s = s; bhs_po = post; bhs_cmp = FHeq; bhs_bd = f_r1; } + f_bdHoareS mt bhs_pr s post FHeq {m;inv=f_r1} | _, _ -> assert false in @@ -229,10 +241,12 @@ let t_bdhoare_call fpre fpost opt_bd tc = let t_equiv_call fpre fpost tc = let env, hyps, _ = FApi.tc1_eflat tc in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in + let fpre = ts_inv_rebind fpre ml mr in + let fpost = ts_inv_rebind fpost ml mr in + let (lpl,fl,argsl),sl = tc1_last_call tc es.es_sl in let (lpr,fr,argsr),sr = tc1_last_call tc es.es_sr in - let ml = EcMemory.memory es.es_ml in - let mr = EcMemory.memory es.es_mr in (* The functions satisfy their specification *) let f_concl = f_equivF fpre fl fr fpost in let modil = f_write env fl in @@ -241,10 +255,10 @@ let t_equiv_call fpre fpost tc = let post = wp2_call env fpre fpost (lpl,fl,argsl) modil (lpr,fr,argsr) modir - ml mr es.es_po hyps + (es_po es) hyps in let concl = - f_equivS_r { es with es_sl = sl; es_sr = sr; es_po = post; } in + f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl sr post in FApi.xmutate1 tc `HlCall [f_concl; concl] @@ -252,40 +266,50 @@ let t_equiv_call fpre fpost tc = let t_equiv_call1 side fpre fpost tc = let env = FApi.tc1_env tc in let equiv = tc1_as_equivS tc in + let ml, mr = fst equiv.es_ml, fst equiv.es_mr in + let mtl, mtr = snd equiv.es_ml, snd equiv.es_mr in let (me, stmt) = match side with | `Left -> (EcMemory.memory equiv.es_ml, equiv.es_sl) | `Right -> (EcMemory.memory equiv.es_mr, equiv.es_sr) in + let wp_asgn_call_side env lv = sideif side + (map_ts_inv_left2 (wp_asgn_call env lv)) + (map_ts_inv_right2 (wp_asgn_call env lv)) + in + let generalize_mod_side = sideif side + generalize_mod_left generalize_mod_right in + let ss_inv_generalize_other_side inv = sideif side + (ss_inv_generalize_right inv mr) (ss_inv_generalize_left inv ml) in let (lp, f, args), fstmt = tc1_last_call tc stmt in let fsig = (Fun.by_xpath f env).f_sig in (* The function satisfies its specification *) - let fconcl = f_bdHoareF fpre f fpost FHeq f_r1 in + let fconcl = f_bdHoareF fpre f fpost FHeq {m=fpost.m; inv=f_r1} in (* WP *) let pvres = pv_res in let vres = LDecl.fresh_id (FApi.tc1_hyps tc) "result" in - let fres = f_local vres fsig.fs_ret in - let post = wp_asgn_call env me lp fres equiv.es_po in - let subst = PVM.add env pvres me fres PVM.empty in - let msubst = Fsubst.f_bind_mem Fsubst.f_subst_id EcFol.mhr me in - let fpost = PVM.subst env subst (Fsubst.f_subst msubst fpost) in + let fres = {ml;mr;inv=f_local vres fsig.fs_ret} in + let post = wp_asgn_call_side env lp fres (es_po equiv) in + let subst = PVM.add env pvres me fres.inv PVM.empty in + let fpost = ss_inv_generalize_other_side (ss_inv_rebind fpost me) in + let fpre = ss_inv_generalize_other_side (ss_inv_rebind fpre me) in + let fpost = map_ts_inv1 (PVM.subst env subst) fpost in let modi = f_write env f in - let post = f_imp_simpl fpost post in - let post = generalize_mod env me modi post in - let post = f_forall_simpl [(vres, GTty fsig.fs_ret)] post in + let post = map_ts_inv2 f_imp_simpl fpost post in + let post = generalize_mod_side env modi post in + let post = map_ts_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) post in let spre = PVM.empty in let spre = subst_args_call env me (e_tuple args) spre in let post = - f_anda_simpl (PVM.subst env spre (Fsubst.f_subst msubst fpre)) post in + map_ts_inv2 f_anda_simpl (map_ts_inv1 (PVM.subst env spre) fpre) post in let concl = match side with - | `Left -> { equiv with es_sl = fstmt; es_po = post; } - | `Right -> { equiv with es_sr = fstmt; es_po = post; } in - let concl = f_equivS_r concl in + | `Left -> f_equivS mtl mtr (es_pr equiv) fstmt equiv.es_sr post + | `Right -> f_equivS mtl mtr (es_pr equiv) equiv.es_sl fstmt post in FApi.xmutate1 tc `HlCall [fconcl; concl] @@ -308,19 +332,19 @@ let t_call side ax tc = let (_, f, _), _ = tc1_last_call tc hs.hs_s in if not (EcEnv.NormMp.x_equal env hf.hf_f f) then call_error env tc hf.hf_f f; - t_hoare_call hf.hf_pr hf.hf_po tc + t_hoare_call (hf_pr hf) (hf_po hf) tc | FeHoareF hf, FeHoareS hs -> let (_, f, _), _ = tc1_last_call tc hs.ehs_s in if not (EcEnv.NormMp.x_equal env hf.ehf_f f) then call_error env tc hf.ehf_f f; - t_ehoare_call hf.ehf_pr hf.ehf_po tc + t_ehoare_call (ehf_pr hf) (ehf_po hf) tc | FbdHoareF hf, FbdHoareS hs -> let (_, f, _), _ = tc1_last_call tc hs.bhs_s in if not (EcEnv.NormMp.x_equal env hf.bhf_f f) then call_error env tc hf.bhf_f f; - t_bdhoare_call hf.bhf_pr hf.bhf_po None tc + t_bdhoare_call (bhf_pr hf) (bhf_po hf) None tc | FequivF ef, FequivS es -> let (_, fl, _), _ = tc1_last_call tc es.es_sl in @@ -336,7 +360,7 @@ let t_call side ax tc = (EcPrinting.pp_funname ppe) ef.ef_fr (EcPrinting.pp_funname ppe) fl (EcPrinting.pp_funname ppe) fr); - t_equiv_call ef.ef_pr ef.ef_po tc + t_equiv_call (ef_pr ef) (ef_po ef) tc | FbdHoareF hf, FequivS _ -> let side = @@ -344,25 +368,26 @@ let t_call side ax tc = | None -> tc_error !!tc "call: a side {1|2} should be provided" | Some side -> side in - t_equiv_call1 side hf.bhf_pr hf.bhf_po tc + t_equiv_call1 side (bhf_pr hf) (bhf_po hf) tc | _, _ -> tc_error !!tc "call: invalid goal shape" (* -------------------------------------------------------------------- *) let mk_inv_spec (_pf : proofenv) env inv fl fr = + let ml, mr = inv.ml, inv.mr in match NormMp.is_abstract_fun fl env with | true -> let (topl, _, _, sigl), (topr, _, _ , sigr) = EcLowPhlGoal.abstract_info2 env fl fr in - let eqglob = f_eqglob topl mleft topr mright in + let eqglob = ts_inv_eqglob topl ml topr mr in let lpre = [eqglob;inv] in let eq_params = - f_eqparams - sigl.fs_arg sigl.fs_anames mleft - sigr.fs_arg sigr.fs_anames mright in - let eq_res = f_eqres sigl.fs_ret mleft sigr.fs_ret mright in - let pre = f_ands (eq_params::lpre) in - let post = f_ands [eq_res; eqglob; inv] in + ts_inv_eqparams + sigl.fs_arg sigl.fs_anames ml + sigr.fs_arg sigr.fs_anames mr in + let eq_res = ts_inv_eqres sigl.fs_ret ml sigr.fs_ret mr in + let pre = map_ts_inv f_ands (eq_params::lpre) in + let post = map_ts_inv f_ands [eq_res; eqglob; inv] in f_equivF pre fl fr post | false -> @@ -376,33 +401,42 @@ let mk_inv_spec (_pf : proofenv) env inv fl fr = if not testty then raise EqObsInError; let eq_params = - f_eqparams - sigl.fs_arg sigl.fs_anames mleft - sigr.fs_arg sigr.fs_anames mright in - let eq_res = f_eqres sigl.fs_ret mleft sigr.fs_ret mright in - let pre = f_and eq_params inv in - let post = f_and eq_res inv in + ts_inv_eqparams + sigl.fs_arg sigl.fs_anames ml + sigr.fs_arg sigr.fs_anames mr in + let eq_res = ts_inv_eqres sigl.fs_ret ml sigr.fs_ret mr in + let pre = map_ts_inv2 f_and eq_params inv in + let post = map_ts_inv2 f_and eq_res inv in f_equivF pre fl fr post let process_call side info tc = - let process_spec tc side = + let process_spec tc side pre post = let (hyps, concl) = FApi.tc1_flat tc in match concl.f_node, side with | FhoareS hs, None -> let (_,f,_) = fst (tc1_last_call tc hs.hs_s) in - let penv, qenv = LDecl.hoareF f hyps in - (penv, qenv, tbool, fun pre post -> f_hoareF pre f post) + let m = (EcIdent.create "&hr") in + let penv, qenv = LDecl.hoareF m f hyps in + let pre = TTC.pf_process_form !!tc penv tbool pre in + let post = TTC.pf_process_form !!tc qenv tbool post in + f_hoareF {m;inv=pre} f {m;inv=post} | FbdHoareS bhs, None -> let (_,f,_) = fst (tc1_last_call tc bhs.bhs_s) in - let penv, qenv = LDecl.hoareF f hyps in - (penv, qenv, tbool, fun pre post -> - bdhoare_call_spec !!tc pre post f bhs.bhs_cmp bhs.bhs_bd None) + let m = (EcIdent.create "&hr") in + let penv, qenv = LDecl.hoareF m f hyps in + let pre = TTC.pf_process_form !!tc penv tbool pre in + let post = TTC.pf_process_form !!tc qenv tbool post in + let bd = ss_inv_rebind (bhs_bd bhs) m in + bdhoare_call_spec !!tc {m;inv=pre} {m;inv=post} f bhs.bhs_cmp bd None | FeHoareS hs, None -> let (_,f,_) = fst (tc1_last_call tc hs.ehs_s) in - let penv, qenv = LDecl.hoareF f hyps in - (penv, qenv, txreal, fun pre post -> f_eHoareF pre f post) + let m = (EcIdent.create "&hr") in + let penv, qenv = LDecl.hoareF m f hyps in + let pre = TTC.pf_process_form !!tc penv txreal pre in + let post = TTC.pf_process_form !!tc qenv txreal post in + f_eHoareF {m;inv=pre} f {m;inv=post} | FbdHoareS _, Some _ | FhoareS _, Some _ -> @@ -411,18 +445,24 @@ let process_call side info tc = | FequivS es, None -> let (_,fl,_) = fst (tc1_last_call tc es.es_sl) in let (_,fr,_) = fst (tc1_last_call tc es.es_sr) in - let penv, qenv = LDecl.equivF fl fr hyps in - (penv, qenv, tbool, fun pre post -> f_equivF pre fl fr post) + let (ml, mr) = (EcIdent.create "&1", EcIdent.create "&2") in + let penv, qenv = LDecl.equivF ml mr fl fr hyps in + let pre = TTC.pf_process_form !!tc penv tbool pre in + let post = TTC.pf_process_form !!tc qenv tbool post in + f_equivF {ml;mr;inv=pre} fl fr {ml;mr;inv=post} | FequivS es, Some side -> let fstmt = sideif side es.es_sl es.es_sr in + let m = sideif side (EcIdent.create "&1") (EcIdent.create "&2") in let (_,f,_) = fst (tc1_last_call tc fstmt) in - let penv, qenv = LDecl.hoareF f hyps in - (penv, qenv, tbool, fun pre post -> f_bdHoareF pre f post FHeq f_r1) + let penv, qenv = LDecl.hoareF m f hyps in + let pre = TTC.pf_process_form !!tc penv tbool pre in + let post = TTC.pf_process_form !!tc qenv tbool post in + f_bdHoareF {m;inv=pre} f {m;inv=post} FHeq {m;inv=f_r1} | _ -> tc_error !!tc "the conclusion is not a hoare or an equiv" in - let process_inv tc side = + let process_inv tc side inv = if not (is_none side) then tc_error !!tc "cannot specify side for call with invariants"; @@ -430,25 +470,42 @@ let process_call side info tc = match concl.f_node with | FhoareS hs -> let (_,f,_) = fst (tc1_last_call tc hs.hs_s) in - let penv = LDecl.inv_memenv1 hyps in - (penv, tbool, fun inv -> f_hoareF inv f inv) + let m = EcIdent.create "&hr" in + let me = EcMemory.abstract m in + let hyps = LDecl.push_active_ss me hyps in + let inv = TTC.pf_process_form !!tc hyps tbool inv in + let inv = {m; inv} in + (f_hoareF inv f inv, Inv_ss inv) | FeHoareS hs -> let (_,f,_) = fst (tc1_last_call tc hs.ehs_s) in - let penv = LDecl.inv_memenv1 hyps in - (penv, txreal, fun inv -> f_eHoareF inv f inv) + let m = EcIdent.create "&hr" in + let me = EcMemory.abstract m in + let hyps = LDecl.push_active_ss me hyps in + let inv = TTC.pf_process_form !!tc hyps txreal inv in + let inv = {m; inv} in + (f_eHoareF inv f inv, Inv_ss inv) | FbdHoareS bhs -> let (_,f,_) = fst (tc1_last_call tc bhs.bhs_s) in - let penv = LDecl.inv_memenv1 hyps in - (penv, tbool, fun inv -> bdhoare_call_spec !!tc inv inv f bhs.bhs_cmp bhs.bhs_bd None) + let m = EcIdent.create "&hr" in + let me = EcMemory.abstract m in + let hyps = LDecl.push_active_ss me hyps in + let inv = TTC.pf_process_form !!tc hyps txreal inv in + let inv = {m; inv} in + let f = bdhoare_call_spec !!tc inv inv f bhs.bhs_cmp (bhs_bd bhs) None in + (f, Inv_ss inv) | FequivS es -> let (_,fl,_) = fst (tc1_last_call tc es.es_sl) in let (_,fr,_) = fst (tc1_last_call tc es.es_sr) in - let penv = LDecl.inv_memenv hyps in + let ml, mr = EcIdent.create "&1", EcIdent.create "&2" in + let mel, mer = EcMemory.abstract ml, EcMemory.abstract mr in + let hyps = LDecl.push_active_ts mel mer hyps in let env = LDecl.toenv hyps in - (penv, tbool, fun inv -> mk_inv_spec !!tc env inv fl fr) + let inv = TTC.pf_process_form !!tc hyps tbool inv in + let inv = {ml;mr; inv} in + (mk_inv_spec !!tc env inv fl fr, Inv_ts inv) | _ -> tc_error !!tc "the conclusion is not a hoare or an equiv" in @@ -463,16 +520,17 @@ let process_call side info tc = let bad,invP,invQ = EcPhlFun.process_fun_upto_info info tc in let (topl,fl,_,sigl), (topr,fr,_ ,sigr) = EcLowPhlGoal.abstract_info2 env fl fr in - let bad2 = Fsubst.f_subst_mem mhr mright bad in - let eqglob = f_eqglob topl mleft topr mright in + let bad2 = ss_inv_generalize_left bad mleft in + let bad2 = ts_inv_rebind bad2 invQ.ml invQ.mr in + let eqglob = ts_inv_eqglob topl mleft topr mright in let lpre = [eqglob;invP] in let eq_params = - f_eqparams + ts_inv_eqparams sigl.fs_arg sigl.fs_anames mleft sigr.fs_arg sigr.fs_anames mright in - let eq_res = f_eqres sigl.fs_ret mleft sigr.fs_ret mright in - let pre = f_if_simpl bad2 invQ (f_ands (eq_params::lpre)) in - let post = f_if_simpl bad2 invQ (f_ands [eq_res;eqglob;invP]) in + let eq_res = ts_inv_eqres sigl.fs_ret mleft sigr.fs_ret mright in + let pre = map_ts_inv3 f_if_simpl bad2 invQ (map_ts_inv f_ands (eq_params::lpre)) in + let post = map_ts_inv3 f_if_simpl bad2 invQ (map_ts_inv f_ands [eq_res;eqglob;invP]) in (bad,invP,invQ, f_equivF pre fl fr post) | _ -> tc_error !!tc "the conclusion is not an equiv" in @@ -482,17 +540,12 @@ let process_call side info tc = let process_cut tc info = match info with | CI_spec (pre, post) -> - let penv,qenv,ty,fmake = process_spec tc side in - let pre = TTC.pf_process_form !!tc penv ty pre in - let post = TTC.pf_process_form !!tc qenv ty post in - fmake pre post - + process_spec tc side pre post | CI_inv inv -> - let hyps, ty, fmake = process_inv tc side in - let inv = TTC.pf_process_form !!tc hyps ty inv in + let f, inv = process_inv tc side inv in subtactic := (fun tc -> FApi.t_firsts t_trivial 2 (EcPhlFun.t_fun inv tc)); - fmake inv + f | CI_upto info -> let bad, p, q, form = process_upto tc side info in @@ -532,28 +585,26 @@ let process_call_concave (fc, info) tc = let (hyps, concl) = FApi.tc1_flat tc in match concl.f_node with | FeHoareS hs -> - let env = LDecl.push_active hs.ehs_m hyps in - TTC.pf_process_form !!tc env (tfun txreal txreal) fc + let env = LDecl.push_active_ss hs.ehs_m hyps in + {m=fst hs.ehs_m;inv=TTC.pf_process_form !!tc env (tfun txreal txreal) fc} | _ -> tc_error !!tc "the conclusion is not a ehoare" in let process_spec tc = - let (hyps, concl) = FApi.tc1_flat tc in + let _, concl = FApi.tc1_flat tc in match concl.f_node with | FeHoareS hs -> let (_,f,_) = fst (tc1_last_call tc hs.ehs_s) in - let penv, qenv = LDecl.hoareF f hyps in - (penv, qenv, txreal, fun pre post -> f_eHoareF pre f post) + (txreal, fun pre post -> f_eHoareF pre f post) | _ -> tc_error !!tc "the conclusion is not a ehoare" in let process_inv tc = - let hyps, concl = FApi.tc1_flat tc in + let _, concl = FApi.tc1_flat tc in match concl.f_node with | FeHoareS hs -> let (_,f,_) = fst (tc1_last_call tc hs.ehs_s) in - let penv = LDecl.inv_memenv1 hyps in - (penv, txreal, fun inv -> f_eHoareF inv f inv) + (txreal, fun inv -> f_eHoareF inv f inv) | _ -> tc_error !!tc "the conclusion is not a ehoare" in @@ -562,16 +613,16 @@ let process_call_concave (fc, info) tc = let process_cut tc info = match info with | CI_spec (pre, post) -> - let penv,qenv,ty,fmake = process_spec tc in - let pre = TTC.pf_process_form !!tc penv ty pre in - let post = TTC.pf_process_form !!tc qenv ty post in + let ty,fmake = process_spec tc in + let _, pre = TTC.tc1_process_Xhl_form tc ty pre in + let _, post = TTC.tc1_process_Xhl_form tc ty post in fmake pre post | CI_inv inv -> - let env, ty, fmake = process_inv tc in - let inv = TTC.pf_process_form !!tc env ty inv in + let ty, fmake = process_inv tc in + let _, inv = TTC.tc1_process_Xhl_form tc ty inv in subtactic := (fun tc -> - FApi.t_firsts t_trivial 2 (EcPhlFun.t_fun inv tc)); + FApi.t_firsts t_trivial 2 (EcPhlFun.t_fun (Inv_ss inv) tc)); fmake inv | _ -> @@ -601,7 +652,7 @@ let process_call_concave (fc, info) tc = let (_, f, _), _ = tc1_last_call tc hs.ehs_s in if not (EcEnv.NormMp.x_equal env hf.ehf_f f) then call_error env tc hf.ehf_f f; - t_ehoare_call_concave fc hf.ehf_pr hf.ehf_po tc + t_ehoare_call_concave fc (ehf_pr hf) (ehf_po hf) tc | _, _ -> tc_error !!tc "call: invalid goal shape" in FApi.t_seqsub diff --git a/src/phl/ecPhlCall.mli b/src/phl/ecPhlCall.mli index 1242522d1..79da81f63 100644 --- a/src/phl/ecPhlCall.mli +++ b/src/phl/ecPhlCall.mli @@ -1,22 +1,22 @@ (* -------------------------------------------------------------------- *) open EcParsetree -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) val wp2_call : - EcEnv.env -> form -> form + EcEnv.env -> ts_inv -> ts_inv -> EcModules.lvalue option * EcPath.xpath * EcTypes.expr list -> EcPV.PV.t -> EcModules.lvalue option * EcPath.xpath * EcTypes.expr list -> EcPV.PV.t - -> EcMemory.memory -> EcMemory.memory -> form - -> EcEnv.LDecl.hyps -> form + -> ts_inv + -> EcEnv.LDecl.hyps -> ts_inv -val t_hoare_call : form -> form -> backward -val t_bdhoare_call : form -> form -> form option -> backward -val t_equiv_call : form -> form -> backward -val t_equiv_call1 : side -> form -> form -> backward +val t_hoare_call : ss_inv -> ss_inv -> backward +val t_bdhoare_call : ss_inv -> ss_inv -> ss_inv option -> backward +val t_equiv_call : ts_inv -> ts_inv -> backward +val t_equiv_call1 : side -> ss_inv -> ss_inv -> backward val t_call : oside -> form -> backward (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlCase.ml b/src/phl/ecPhlCase.ml index 35597fb81..069c05035 100644 --- a/src/phl/ecPhlCase.ml +++ b/src/phl/ecPhlCase.ml @@ -2,39 +2,43 @@ open EcFol open EcCoreGoal open EcLowPhlGoal +open EcAst (* --------------------------------------------------------------------- *) let t_hoare_case_r ?(simplify = true) f tc = let fand = if simplify then f_and_simpl else f_and in let hs = tc1_as_hoareS tc in - let concl1 = f_hoareS_r { hs with hs_pr = fand hs.hs_pr f } in - let concl2 = f_hoareS_r { hs with hs_pr = fand hs.hs_pr (f_not f) } in + let mt = snd hs.hs_m in + let concl1 = f_hoareS mt (map_ss_inv2 fand (hs_pr hs) f) hs.hs_s (hs_po hs) in + let concl2 = f_hoareS mt (map_ss_inv2 fand (hs_pr hs) (map_ss_inv1 f_not f)) hs.hs_s (hs_po hs) in FApi.xmutate1 tc (`HlCase f) [concl1; concl2] (* --------------------------------------------------------------------- *) let t_ehoare_case_r ?(simplify = true) f tc = let _ = simplify in let hs = tc1_as_ehoareS tc in - let concl1 = f_eHoareS_r { hs with ehs_pr = f_interp_ehoare_form f hs.ehs_pr } in - let concl2 = f_eHoareS_r { hs with ehs_pr = f_interp_ehoare_form (f_not f) hs.ehs_pr} in + let mt = snd hs.ehs_m in + let concl1 = f_eHoareS mt (map_ss_inv2 f_interp_ehoare_form f (ehs_pr hs)) hs.ehs_s (ehs_po hs) in + let concl2 = f_eHoareS mt (map_ss_inv2 f_interp_ehoare_form (map_ss_inv1 f_not f) (ehs_pr hs)) hs.ehs_s (ehs_po hs) in FApi.xmutate1 tc (`HlCase f) [concl1; concl2] (* --------------------------------------------------------------------- *) let t_bdhoare_case_r ?(simplify = true) f tc = let fand = if simplify then f_and_simpl else f_and in let bhs = tc1_as_bdhoareS tc in - let concl1 = f_bdHoareS_r - { bhs with bhs_pr = fand bhs.bhs_pr f } in - let concl2 = f_bdHoareS_r - { bhs with bhs_pr = fand bhs.bhs_pr (f_not f) } in + let mt = snd bhs.bhs_m in + let concl1 = f_bdHoareS mt (map_ss_inv2 fand (bhs_pr bhs) f) bhs.bhs_s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in + let concl2 = f_bdHoareS mt + (map_ss_inv2 fand (bhs_pr bhs) (map_ss_inv1 f_not f)) bhs.bhs_s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc (`HlCase f) [concl1; concl2] (* --------------------------------------------------------------------- *) let t_equiv_case_r ?(simplify = true) f tc = let fand = if simplify then f_and_simpl else f_and in let es = tc1_as_equivS tc in - let concl1 = f_equivS_r { es with es_pr = fand es.es_pr f } in - let concl2 = f_equivS_r { es with es_pr = fand es.es_pr (f_not f) } in + let mtl, mtr = snd es.es_ml, snd es.es_mr in + let concl1 = f_equivS mtl mtr (map_ts_inv2 fand (es_pr es) f) es.es_sl es.es_sr (es_po es) in + let concl2 = f_equivS mtl mtr (map_ts_inv2 fand (es_pr es) (map_ts_inv1 f_not f)) es.es_sl es.es_sr (es_po es) in FApi.xmutate1 tc (`HlCase f) [concl1; concl2] (* --------------------------------------------------------------------- *) @@ -52,12 +56,23 @@ let t_equiv_case ?simplify = (* --------------------------------------------------------------------- *) let t_hl_case_r ?simplify f tc = - t_hS_or_bhS_or_eS - ~th:(t_hoare_case ?simplify f) - ~teh:(t_ehoare_case ?simplify f) - ~tbh:(t_bdhoare_case ?simplify f) - ~te:(t_equiv_case ?simplify f) - tc + match f with + | Inv_ss f -> + t_hS_or_bhS_or_eS + ~th:(t_hoare_case ?simplify f) + ~teh:(t_ehoare_case ?simplify f) + ~tbh:(t_bdhoare_case ?simplify f) + ~te:(fun _ -> tc_error !!tc "expecting a two sided formula") + tc + | Inv_ts f -> + let err _ = + tc_error !!tc "expecting a one sided formula" in + t_hS_or_bhS_or_eS + ~th:err + ~teh:err + ~tbh:err + ~te:(t_equiv_case ?simplify f) + tc (* -------------------------------------------------------------------- *) let t_hl_case ?simplify = FApi.t_low1 "hl-case" (t_hl_case_r ?simplify) diff --git a/src/phl/ecPhlCase.mli b/src/phl/ecPhlCase.mli index 9c156e68d..2d46e3f6c 100644 --- a/src/phl/ecPhlCase.mli +++ b/src/phl/ecPhlCase.mli @@ -1,10 +1,10 @@ (* -------------------------------------------------------------------- *) -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) -val t_hoare_case : ?simplify:bool -> form -> backward -val t_bdhoare_case : ?simplify:bool -> form -> backward -val t_equiv_case : ?simplify:bool -> form -> backward +val t_hoare_case : ?simplify:bool -> ss_inv -> backward +val t_bdhoare_case : ?simplify:bool -> ss_inv -> backward +val t_equiv_case : ?simplify:bool -> ts_inv -> backward -val t_hl_case : ?simplify:bool -> form -> backward +val t_hl_case : ?simplify:bool -> inv -> backward diff --git a/src/phl/ecPhlCodeTx.ml b/src/phl/ecPhlCodeTx.ml index b4022c282..0cc9e48b4 100644 --- a/src/phl/ecPhlCodeTx.ml +++ b/src/phl/ecPhlCodeTx.ml @@ -72,8 +72,8 @@ let t_kill_r side cpos olen tc = "code writes variables (%a) used by the post-condition" pp_of_name x end; - - let kslconcl = EcFol.f_bdHoareS me f_true (stmt ks) f_true FHeq f_r1 in + let (m, mt) = me in + let kslconcl = EcFol.f_bdHoareS mt {m;inv=f_true} (stmt ks) {m;inv=f_true} FHeq {m;inv=f_r1} in (me, { zpr with Zpr.z_tail = tl; }, [kslconcl]) in @@ -155,23 +155,24 @@ let set_match_stmt (id : symbol) ((ue, mev, ptn) : _ * _ * form) = try let ptev = EcProofTerm.ptenv pe hyps (ue, mev) in - let e = form_of_expr (fst me) e in - let subf, occmode = EcProofTerm.pf_find_occurence_lazy ptev ~ptn e in + let e = ss_inv_of_expr (fst me) e in + let subf, occmode = EcProofTerm.pf_find_occurence_lazy ptev ~ptn e.inv in + let subf = {m=e.m; inv= subf} in assert (EcProofTerm.can_concretize ptev); let cpos = EcMatching.FPosition.select_form ~xconv:`AlphaEq ~keyed:occmode.k_keyed - hyps None subf e in + hyps None subf.inv e.inv in - let v = { ov_name = Some id; ov_type = subf.f_ty } in + let v = { ov_name = Some id; ov_type = subf.inv.f_ty } in let (me, id) = EcMemory.bind_fresh v me in let pv = pv_loc (oget id.ov_name) in - let e = EcMatching.FPosition.map cpos (fun _ -> f_pvar pv (subf.f_ty) (fst me)) e in + let e = map_ss_inv2 (fun pv -> EcMatching.FPosition.map cpos (fun _ -> pv)) (f_pvar pv (subf.inv.f_ty) (fst me)) e in - let i1 = i_asgn (LvVar (pv, subf.f_ty), expr_of_form (fst me) subf) in - let i2 = mk (expr_of_form (fst me) e) in + let i1 = i_asgn (LvVar (pv, subf.inv.f_ty), expr_of_ss_inv subf) in + let i2 = mk (expr_of_ss_inv e) in (me, { z with z_tail = i1 :: i2 :: is }, []) @@ -189,9 +190,9 @@ let cfold_stmt ?(simplify = true) (pf, hyps) (me : memenv) (olen : int option) ( let simplify : expr -> expr = if simplify then (fun e -> - let e = form_of_expr (fst me) e in - let e = EcReduction.simplify EcReduction.nodelta hyps e in - let e = expr_of_form (fst me) e in + let e = ss_inv_of_expr (fst me) e in + let e = map_ss_inv1 (EcReduction.simplify EcReduction.nodelta hyps) e in + let e = expr_of_ss_inv e in e ) else identity in @@ -360,7 +361,7 @@ let process_set (side, cpos, fresh, id, e) tc = let process_set_match (side, cpos, id, pattern) tc = let cpos = EcProofTyping.tc1_process_codepos tc (side, cpos) in let me, _ = tc1_get_stmt side tc in - let hyps = LDecl.push_active me (FApi.tc1_hyps tc) in + let hyps = LDecl.push_active_ss me (FApi.tc1_hyps tc) in let ue = EcProofTyping.unienv_of_hyps hyps in let ptnmap = ref Mid.empty in let pattern = EcTyping.trans_pattern (LDecl.toenv hyps) ptnmap ue pattern in @@ -395,27 +396,27 @@ let process_weakmem (side, id, params) tc = let h = match f.f_node with | FhoareS hs -> - let me = bind hs.hs_m in - f_hoareS_r { hs with hs_m = me } + let _, mt = bind hs.hs_m in + f_hoareS mt (hs_pr hs) hs.hs_s (hs_po hs) | FeHoareS hs -> - let me = bind hs.ehs_m in - f_eHoareS_r { hs with ehs_m = me } + let _, mt = bind hs.ehs_m in + f_eHoareS mt (ehs_pr hs) hs.ehs_s (ehs_po hs) | FbdHoareS hs -> - let me = bind hs.bhs_m in - f_bdHoareS_r { hs with bhs_m = me } + let _, mt = bind hs.bhs_m in + f_bdHoareS mt (bhs_pr hs) hs.bhs_s (bhs_po hs) hs.bhs_cmp (bhs_bd hs) | FequivS es -> - let do_side side es = - let es_ml, es_mr = if side = `Left then bind es.es_ml, es.es_mr else es.es_ml, bind es.es_mr in - {es with es_ml; es_mr} + let do_side side (ml, mr) = + let es_ml, es_mr = if side = `Left then bind ml, mr else ml, bind mr in + (es_ml, es_mr) in - let es = + let ((_, mtl), (_, mtr)) = match side with - | None -> do_side `Left (do_side `Right es) - | Some side -> do_side side es in - f_equivS_r es + | None -> do_side `Left (do_side `Right (es.es_ml, es.es_mr)) + | Some side -> do_side side (es.es_ml, es.es_mr) in + f_equivS mtl mtr (es_pr es) es.es_sl es.es_sr (es_po es) | _ -> tc_error ~loc:id.pl_loc !!tc diff --git a/src/phl/ecPhlCond.ml b/src/phl/ecPhlCond.ml index 300e50bb1..78bb6759a 100644 --- a/src/phl/ecPhlCond.ml +++ b/src/phl/ecPhlCond.ml @@ -3,6 +3,7 @@ open EcUtils open EcTypes open EcFol open EcEnv +open EcAst open EcCoreGoal open EcLowGoal @@ -47,25 +48,26 @@ end let t_hoare_cond tc = let hs = tc1_as_hoareS tc in let (e,_,_) = fst (tc1_first_if tc hs.hs_s) in - LowInternal.t_gen_cond None (form_of_expr (EcMemory.memory hs.hs_m) e) tc + LowInternal.t_gen_cond None (Inv_ss (ss_inv_of_expr (EcMemory.memory hs.hs_m) e)) tc (* -------------------------------------------------------------------- *) let t_ehoare_cond tc = let hs = tc1_as_ehoareS tc in let (e,_,_) = fst (tc1_first_if tc hs.ehs_s) in LowInternal.t_gen_cond ~t_finalize:LowInternal.t_finalize_ehoare - None (form_of_expr (EcMemory.memory hs.ehs_m) e) tc + None (Inv_ss (ss_inv_of_expr (EcMemory.memory hs.ehs_m) e)) tc (* -------------------------------------------------------------------- *) let t_bdhoare_cond tc = let bhs = tc1_as_bdhoareS tc in let (e,_,_) = fst (tc1_first_if tc bhs.bhs_s) in - LowInternal.t_gen_cond None (form_of_expr (EcMemory.memory bhs.bhs_m) e) tc + LowInternal.t_gen_cond None (Inv_ss (ss_inv_of_expr (EcMemory.memory bhs.bhs_m) e)) tc (* -------------------------------------------------------------------- *) let rec t_equiv_cond side tc = let hyps = FApi.tc1_hyps tc in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in match side with | Some s -> @@ -73,21 +75,20 @@ let rec t_equiv_cond side tc = match s with | `Left -> let (e,_,_) = fst (tc1_first_if tc es.es_sl) in - form_of_expr (EcMemory.memory es.es_ml) e + ss_inv_generalize_right (ss_inv_of_expr ml e) mr | `Right -> let (e,_,_) = fst (tc1_first_if tc es.es_sr) in - form_of_expr (EcMemory.memory es.es_mr) e - in LowInternal.t_gen_cond side e tc + ss_inv_generalize_left (ss_inv_of_expr mr e) ml + in LowInternal.t_gen_cond side (Inv_ts e) tc | None -> let el,_,_ = fst (tc1_first_if tc es.es_sl) in let er,_,_ = fst (tc1_first_if tc es.es_sr) in - let el = form_of_expr (EcMemory.memory es.es_ml) el in - let er = form_of_expr (EcMemory.memory es.es_mr) er in + let el = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let er = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in let fiff = - f_forall_mems - [es.es_ml;es.es_mr] - (f_imp es.es_pr (f_iff el er)) in + EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr + (map_ts_inv2 f_imp (es_pr es) (map_ts_inv2 f_iff el er)) in let fresh = ["hiff";"&m1";"&m2";"h";"h";"h"] in let fresh = LDecl.fresh_ids hyps fresh in @@ -131,7 +132,17 @@ end = struct let (e, _), _ = tc1_first_match tc st in let _, indt, _ = oget (EcEnv.Ty.get_top_decl e.e_ty env) in let indt = oget (EcDecl.tydecl_as_datatype indt) in - let f = form_of_expr (EcMemory.memory me) e in + let f = + let f = ss_inv_of_expr (EcMemory.memory me) e in + let pre = tc1_get_pre tc in + match pre, side with + | Inv_ts {mr}, Some `Left -> + Inv_ts (ss_inv_generalize_right f mr) + | Inv_ts {ml}, Some `Right -> + Inv_ts (ss_inv_generalize_left f ml) + | Inv_ss f, _ -> + Inv_ss f + | Inv_ts _, None -> tc_error !!tc "expecting a side" in let onsub (i : int) (tc : tcenv1) = let cname, cargs = List.nth indt.tydt_ctors i in @@ -175,8 +186,10 @@ end = struct let clean (tc : tcenv1) = let pre = oget (EcLowPhlGoal.get_pre (FApi.tc1_goal tc)) in let post = oget (EcLowPhlGoal.get_post (FApi.tc1_goal tc)) in - let eq, _, pre = destr_and3 pre in - let tc = EcPhlConseq.t_conseq (f_and eq pre) post tc in + let pre = map_inv1 (fun pre -> + let eq, _, pre = destr_and3 pre in + f_and eq pre) pre in + let tc = EcPhlConseq.t_conseq pre post tc in FApi.t_onall (EcLowGoal.t_clears names) @@ -215,6 +228,7 @@ let t_equiv_match_same_constr tc = let hyps = FApi.tc1_hyps tc in let env = LDecl.toenv hyps in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in let (el, bsl), sl = tc1_first_match tc es.es_sl in let (er, bsr), sr = tc1_first_match tc es.es_sr in @@ -226,44 +240,45 @@ let t_equiv_match_same_constr tc = tc_error !!tc "match statements on different inductive types"; let dt = oget (EcDecl.tydecl_as_datatype dt) in - let fl = form_of_expr (EcMemory.memory es.es_ml) el in - let fr = form_of_expr (EcMemory.memory es.es_mr) er in + let fl = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let fr = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in let get_eqv_cond ((c, _), ((cl, _), (cr, _))) = let bhl = List.map (fst_map EcIdent.fresh) cl in let bhr = List.map (fst_map EcIdent.fresh) cr in let cop = EcPath.pqoname (EcPath.prefix pl) c in - let copl = f_op cop tyl (toarrow (List.snd cl) fl.f_ty) in - let copr = f_op cop tyr (toarrow (List.snd cr) fr.f_ty) in + let copl = f_op cop tyl (toarrow (List.snd cl) fl.inv.f_ty) in + let copr = f_op cop tyr (toarrow (List.snd cr) fr.inv.f_ty) in - let lhs = f_eq fl (f_app copl (List.map (curry f_local) bhl) fl.f_ty) in - let lhs = f_exists (List.map (snd_map gtty) bhl) lhs in + let lhs = map_ts_inv1 (fun fl -> f_eq fl (f_app copl (List.map (curry f_local) bhl) fl.f_ty)) fl in + let lhs = map_ts_inv1 (f_exists (List.map (snd_map gtty) bhl)) lhs in - let rhs = f_eq fr (f_app copr (List.map (curry f_local) bhr) fr.f_ty) in - let rhs = f_exists (List.map (snd_map gtty) bhr) rhs in + let rhs = map_ts_inv1 (fun fr -> f_eq fr (f_app copr (List.map (curry f_local) bhr) fr.f_ty)) fr in + let rhs = map_ts_inv1 (f_exists (List.map (snd_map gtty) bhr)) rhs in - f_forall_mems [es.es_ml; es.es_mr] (f_imp_simpl es.es_pr (f_iff lhs rhs)) in + EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr + (map_ts_inv2 f_imp_simpl (es_pr es) (map_ts_inv2 f_iff lhs rhs)) in let get_eqv_goal ((c, _), ((cl, bl), (cr, br))) = let sb = Fsubst.f_subst_id in let sb, bhl = add_elocals sb cl in let sb, bhr = add_elocals sb cr in let cop = EcPath.pqoname (EcPath.prefix pl) c in - let copl = f_op cop tyl (toarrow (List.snd cl) fl.f_ty) in - let copr = f_op cop tyr (toarrow (List.snd cr) fr.f_ty) in - let pre = f_ands_simpl - [ f_eq fl (f_app copl (List.map (curry f_local) bhl) fl.f_ty); - f_eq fr (f_app copr (List.map (curry f_local) bhr) fr.f_ty) ] - es.es_pr in + let copl = f_op cop tyl (toarrow (List.snd cl) fl.inv.f_ty) in + let copr = f_op cop tyr (toarrow (List.snd cr) fr.inv.f_ty) in + let f_ands_simpl' f = f_ands_simpl (List.tl f) (List.hd f) in + let pre = map_ts_inv f_ands_simpl' + [es_pr es; map_ts_inv1 (fun fl -> f_eq fl (f_app copl (List.map (curry f_local) bhl) fl.f_ty)) fl; + map_ts_inv1 (fun fr -> f_eq fr (f_app copr (List.map (curry f_local) bhr) fr.f_ty)) fr ] + in f_forall ( (List.map (snd_map gtty) bhl) @ (List.map (snd_map gtty) bhr) ) - ( f_equivS_r - { es with - es_sl = EcModules.stmt ((s_subst sb bl).s_node @ sl.s_node); - es_sr = EcModules.stmt ((s_subst sb br).s_node @ sr.s_node); - es_pr = pre; } ) + ( f_equivS (snd es.es_ml) (snd es.es_mr) pre + (EcModules.stmt ((s_subst sb bl).s_node @ sl.s_node)) + (EcModules.stmt ((s_subst sb br).s_node @ sr.s_node)) + (es_po es)) in @@ -280,6 +295,7 @@ let t_equiv_match_eq tc = let hyps = FApi.tc1_hyps tc in let env = LDecl.toenv hyps in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in let (el, bsl), sl = tc1_first_match tc es.es_sl in let (er, bsr), sr = tc1_first_match tc es.es_sr in @@ -294,12 +310,12 @@ let t_equiv_match_eq tc = tc_error !!tc "synced match requires matches on the same type"; let dt = oget (EcDecl.tydecl_as_datatype dt) in - let fl = form_of_expr (EcMemory.memory es.es_ml) el in - let fr = form_of_expr (EcMemory.memory es.es_mr) er in + let fl = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let fr = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in let eqv_cond = - f_forall_mems [es.es_ml; es.es_mr] - (f_imp_simpl es.es_pr (f_eq fl fr)) in + EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr + (map_ts_inv2 f_imp_simpl (es_pr es) (map_ts_inv2 f_eq fl fr)) in let get_eqv_goal ((c, _), ((cl, bl), (cr, br))) = let sb = f_subst_init () in @@ -312,20 +328,19 @@ let t_equiv_match_eq tc = sb cl cr in let cop = EcPath.pqoname (EcPath.prefix pl) c in - let copl = f_op cop tyl (toarrow (List.snd cl) fl.f_ty) in - let copr = f_op cop tyr (toarrow (List.snd cr) fr.f_ty) in - let pre = f_ands_simpl - [ f_eq fl (f_app copl (List.map (curry f_local) bh) fl.f_ty); - f_eq fr (f_app copr (List.map (curry f_local) bh) fr.f_ty) ] - es.es_pr in + let copl = f_op cop tyl (toarrow (List.snd cl) fl.inv.f_ty) in + let copr = f_op cop tyr (toarrow (List.snd cr) fr.inv.f_ty) in + let f_ands_simpl' f = f_ands_simpl (List.tl f) (List.hd f) in + let pre = map_ts_inv f_ands_simpl' + [ es_pr es; map_ts_inv1 (fun fl -> f_eq fl (f_app copl (List.map (curry f_local) bh) fl.f_ty)) fl; + map_ts_inv1 (fun fr -> f_eq fr (f_app copr (List.map (curry f_local) bh) fr.f_ty)) fr ] in f_forall (List.map (snd_map gtty) bh) - (f_equivS_r - { es with - es_sl = EcModules.stmt ((s_subst sb bl).s_node @ sl.s_node); - es_sr = EcModules.stmt ((s_subst sb br).s_node @ sr.s_node); - es_pr = pre; } ) + (f_equivS (snd es.es_ml) (snd es.es_mr) pre + (EcModules.stmt ((s_subst sb bl).s_node @ sl.s_node)) + (EcModules.stmt ((s_subst sb br).s_node @ sr.s_node)) + (es_po es)) in diff --git a/src/phl/ecPhlConseq.ml b/src/phl/ecPhlConseq.ml index 5627676a7..e03cc3674 100644 --- a/src/phl/ecPhlConseq.ml +++ b/src/phl/ecPhlConseq.ml @@ -7,6 +7,8 @@ open EcModules open EcFol open EcEnv open EcPV +open EcSubst +open EcReduction open EcCoreGoal open EcLowGoal @@ -16,9 +18,11 @@ module PT = EcProofTerm module TTC = EcProofTyping (* -------------------------------------------------------------------- *) -let conseq_cond pre post spre spost = - f_imp pre spre, f_imp spost post +let conseq_cond_ss pre post spre spost = + map_ss_inv2 f_imp pre spre, map_ss_inv2 f_imp spost post +let conseq_cond_ts pre post spre spost = + map_ts_inv2 f_imp pre spre, map_ts_inv2 f_imp spost post (* { sF } c { sf } sF <= F f <= sf @@ -26,15 +30,19 @@ let conseq_cond pre post spre spost = { F } c { f } *) let conseq_econd pre post spre spost = - f_xreal_le spre pre, f_xreal_le post spost + map_ss_inv2 f_xreal_le spre pre, map_ss_inv2 f_xreal_le post spost let bd_goal_r fcmp fbd cmp bd = match fcmp, cmp with - | FHle, (FHle | FHeq) -> Some (f_real_le bd fbd) - | FHge, (FHge | FHeq) -> Some (f_real_le fbd bd) - | FHeq, FHeq -> Some (f_eq bd fbd) - | FHeq, FHge -> Some (f_and (f_eq fbd f_r1) (f_eq bd f_r1)) - | FHeq, FHle -> Some (f_and (f_eq fbd f_r0) (f_eq bd f_r0)) + | FHle, (FHle | FHeq) -> Some (map_ss_inv2 f_real_le bd fbd) + | FHge, (FHge | FHeq) -> Some (map_ss_inv2 f_real_le fbd bd) + | FHeq, FHeq -> Some (map_ss_inv2 f_eq bd fbd) + | FHeq, FHge -> Some (map_ss_inv2 f_and + (map_ss_inv1 ((EcUtils.flip f_eq) f_r1) fbd) + (map_ss_inv1 ((EcUtils.flip f_eq) f_r1) bd)) + | FHeq, FHle -> Some (map_ss_inv2 f_and + (map_ss_inv1 ((EcUtils.flip f_eq) f_r0) fbd) + (map_ss_inv1 ((EcUtils.flip f_eq) f_r0) bd)) | _ , _ -> None let bd_goal tc fcmp fbd cmp bd = @@ -43,39 +51,41 @@ let bd_goal tc fcmp fbd cmp bd = let ppe = EcPrinting.PPEnv.ofenv (FApi.tc1_env tc) in tc_error !!tc "do not know how to change phoare[...]%s %a into phoare[...]%s %a" - (EcPrinting.string_of_hcmp fcmp) (EcPrinting.pp_form ppe) fbd - (EcPrinting.string_of_hcmp cmp) (EcPrinting.pp_form ppe) bd + (EcPrinting.string_of_hcmp fcmp) (EcPrinting.pp_form ppe) fbd.inv + (EcPrinting.string_of_hcmp cmp) (EcPrinting.pp_form ppe) bd.inv | Some fp -> fp (* -------------------------------------------------------------------- *) let t_hoareF_conseq pre post tc = let env = FApi.tc1_env tc in let hf = tc1_as_hoareF tc in - let mpr,mpo = EcEnv.Fun.hoareF_memenv hf.hf_f env in - let cond1, cond2 = conseq_cond hf.hf_pr hf.hf_po pre post in - let concl1 = f_forall_mems [mpr] cond1 in - let concl2 = f_forall_mems [mpo] cond2 in + let pre = ss_inv_rebind pre hf.hf_m in + let post = ss_inv_rebind post hf.hf_m in + let mpr,mpo = EcEnv.Fun.hoareF_memenv hf.hf_m hf.hf_f env in + let cond1, cond2 = conseq_cond_ss (hf_pr hf) (hf_po hf) pre post in + let concl1 = f_forall_mems_ss_inv mpr cond1 in + let concl2 = f_forall_mems_ss_inv mpo cond2 in let concl3 = f_hoareF pre hf.hf_f post in FApi.xmutate1 tc `Conseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_hoareS_conseq pre post tc = let hs = tc1_as_hoareS tc in - let cond1, cond2 = conseq_cond hs.hs_pr hs.hs_po pre post in - let concl1 = f_forall_mems [hs.hs_m] cond1 in - let concl2 = f_forall_mems [hs.hs_m] cond2 in - let concl3 = f_hoareS_r { hs with hs_pr = pre; hs_po = post } in + let cond1, cond2 = conseq_cond_ss (hs_pr hs) (hs_po hs) pre post in + let concl1 = f_forall_mems_ss_inv hs.hs_m cond1 in + let concl2 = f_forall_mems_ss_inv hs.hs_m cond2 in + let concl3 = f_hoareS (snd hs.hs_m) pre hs.hs_s post in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_ehoareF_conseq pre post tc = let env = FApi.tc1_env tc in let hf = tc1_as_ehoareF tc in - let mpr,mpo = EcEnv.Fun.hoareF_memenv hf.ehf_f env in + let mpr,mpo = EcEnv.Fun.hoareF_memenv hf.ehf_m hf.ehf_f env in let cond1, cond2 = - conseq_econd hf.ehf_pr hf.ehf_po pre post in - let concl1 = f_forall_mems [mpr] cond1 in - let concl2 = f_forall_mems [mpo] cond2 in + conseq_econd (ehf_pr hf) (ehf_po hf) pre post in + let concl1 = f_forall_mems_ss_inv mpr cond1 in + let concl2 = f_forall_mems_ss_inv mpo cond2 in let concl3 = f_eHoareF pre hf.ehf_f post in FApi.xmutate1 tc `Conseq [concl1; concl2; concl3] @@ -83,59 +93,70 @@ let t_ehoareF_conseq pre post tc = let t_ehoareS_conseq pre post tc = let hs = tc1_as_ehoareS tc in let cond1, cond2 = - conseq_econd hs.ehs_pr hs.ehs_po pre post in - let concl1 = f_forall_mems [hs.ehs_m] cond1 in - let concl2 = f_forall_mems [hs.ehs_m] cond2 in - let concl3 = f_eHoareS_r { hs with ehs_pr = pre; ehs_po = post; } in + conseq_econd (ehs_pr hs) (ehs_po hs) pre post in + let concl1 = f_forall_mems_ss_inv hs.ehs_m cond1 in + let concl2 = f_forall_mems_ss_inv hs.ehs_m cond2 in + let concl3 = f_eHoareS (snd hs.ehs_m) pre hs.ehs_s post in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) + let bdHoare_conseq_conds cmp pr po new_pr new_po = - let cond1, cond2 = conseq_cond pr po new_pr new_po in + let cond1, cond2 = conseq_cond_ss pr po new_pr new_po in let cond2 = match cmp with - | FHle -> f_imp po new_po - | FHeq -> f_iff po new_po + | FHle -> map_ss_inv2 f_imp po new_po + | FHeq -> map_ss_inv2 f_iff po new_po | FHge -> cond2 in cond1, cond2 +(* -------------------------------------------------------------------- *) + let t_bdHoareF_conseq pre post tc = let env = FApi.tc1_env tc in let bhf = tc1_as_bdhoareF tc in - let mpr,mpo = EcEnv.Fun.hoareF_memenv bhf.bhf_f env in + let mpr,mpo = EcEnv.Fun.hoareF_memenv bhf.bhf_m bhf.bhf_f env in + let pre = ss_inv_rebind pre bhf.bhf_m in + let post = ss_inv_rebind post bhf.bhf_m in let cond1, cond2 = - bdHoare_conseq_conds bhf.bhf_cmp bhf.bhf_pr bhf.bhf_po pre post in - let concl1 = f_forall_mems [mpr] cond1 in - let concl2 = f_forall_mems [mpo] cond2 in - let concl3 = f_bdHoareF pre bhf.bhf_f post bhf.bhf_cmp bhf.bhf_bd in + bdHoare_conseq_conds bhf.bhf_cmp (bhf_pr bhf) (bhf_po bhf) pre post in + let concl1 = f_forall_mems_ss_inv mpr cond1 in + let concl2 = f_forall_mems_ss_inv mpo cond2 in + let concl3 = f_bdHoareF pre bhf.bhf_f post bhf.bhf_cmp (bhf_bd bhf) in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_bdHoareS_conseq pre post tc = let bhs = tc1_as_bdhoareS tc in + let pre = ss_inv_rebind pre (fst bhs.bhs_m) in + let post = ss_inv_rebind post (fst bhs.bhs_m) in let cond1, cond2 = - bdHoare_conseq_conds bhs.bhs_cmp bhs.bhs_pr bhs.bhs_po pre post in - let concl1 = f_forall_mems [bhs.bhs_m] cond1 in - let concl2 = f_forall_mems [bhs.bhs_m] cond2 in - let concl3 = f_bdHoareS_r { bhs with bhs_pr = pre; bhs_po = post } in + bdHoare_conseq_conds bhs.bhs_cmp (bhs_pr bhs) (bhs_po bhs) pre post in + let concl1 = f_forall_mems_ss_inv bhs.bhs_m cond1 in + let concl2 = f_forall_mems_ss_inv bhs.bhs_m cond2 in + let concl3 = f_bdHoareS (snd bhs.bhs_m) pre bhs.bhs_s post bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_bdHoareF_conseq_bd cmp bd tc = let env = FApi.tc1_env tc in let bhf = tc1_as_bdhoareF tc in - let mpr,_ = EcEnv.Fun.hoareF_memenv bhf.bhf_f env in - let bd_goal = bd_goal tc bhf.bhf_cmp bhf.bhf_bd cmp bd in - let concl = f_bdHoareF bhf.bhf_pr bhf.bhf_f bhf.bhf_po cmp bd in - let bd_goal = f_forall_mems [mpr] (f_imp bhf.bhf_pr bd_goal) in + let bd = ss_inv_rebind bd bhf.bhf_m in + let mpr,_ = EcEnv.Fun.hoareF_memenv bhf.bhf_m bhf.bhf_f env in + let bd_goal = bd_goal tc bhf.bhf_cmp (bhf_bd bhf) cmp bd in + let concl = f_bdHoareF (bhf_pr bhf) bhf.bhf_f (bhf_po bhf) cmp bd in + let goal = map_ss_inv2 f_imp (bhf_pr bhf) bd_goal in + let bd_goal = f_forall_mems_ss_inv mpr goal in FApi.xmutate1 tc `HlConseq [bd_goal; concl] (* -------------------------------------------------------------------- *) let t_bdHoareS_conseq_bd cmp bd tc = let bhs = tc1_as_bdhoareS tc in - let bd_goal = bd_goal tc bhs.bhs_cmp bhs.bhs_bd cmp bd in - let concl = f_bdHoareS bhs.bhs_m bhs.bhs_pr bhs.bhs_s bhs.bhs_po cmp bd in - let bd_goal = f_forall_mems [bhs.bhs_m] (f_imp bhs.bhs_pr bd_goal) in + let bd = ss_inv_rebind bd (fst bhs.bhs_m) in + let bd_goal = bd_goal tc bhs.bhs_cmp (bhs_bd bhs) cmp bd in + let concl = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) bhs.bhs_s (bhs_po bhs) cmp bd in + let imp = map_ss_inv2 f_imp (bhs_pr bhs) bd_goal in + let bd_goal = f_forall_mems_ss_inv bhs.bhs_m imp in FApi.xmutate1 tc `HlConseq [bd_goal; concl] (* -------------------------------------------------------------------- *) @@ -143,10 +164,12 @@ let t_equivF_conseq pre post tc = let env = FApi.tc1_env tc in let ef = tc1_as_equivF tc in let (mprl,mprr), (mpol,mpor) = - EcEnv.Fun.equivF_memenv ef.ef_fl ef.ef_fr env in - let cond1, cond2 = conseq_cond ef.ef_pr ef.ef_po pre post in - let concl1 = f_forall_mems [mprl;mprr] cond1 in - let concl2 = f_forall_mems [mpol;mpor] cond2 in + EcEnv.Fun.equivF_memenv ef.ef_ml ef.ef_mr ef.ef_fl ef.ef_fr env in + let pre = ts_inv_rebind pre ef.ef_ml ef.ef_mr in + let post = ts_inv_rebind post ef.ef_ml ef.ef_mr in + let cond1, cond2 = conseq_cond_ts (ef_pr ef) (ef_po ef) pre post in + let concl1 = f_forall_mems_ts_inv mprl mprr cond1 in + let concl2 = f_forall_mems_ts_inv mpol mpor cond2 in let concl3 = f_equivF pre ef.ef_fl ef.ef_fr post in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] @@ -155,34 +178,38 @@ let t_eagerF_conseq pre post tc = let env = FApi.tc1_env tc in let eg = tc1_as_eagerF tc in let (mprl,mprr), (mpol,mpor) = - EcEnv.Fun.equivF_memenv eg.eg_fl eg.eg_fr env in - let cond1, cond2 = conseq_cond eg.eg_pr eg.eg_po pre post in - let concl1 = f_forall_mems [mprl;mprr] cond1 in - let concl2 = f_forall_mems [mpol;mpor] cond2 in + EcEnv.Fun.equivF_memenv eg.eg_ml eg.eg_mr eg.eg_fl eg.eg_fr env in + let pre = ts_inv_rebind pre eg.eg_ml eg.eg_mr in + let post = ts_inv_rebind post eg.eg_ml eg.eg_mr in + let cond1, cond2 = conseq_cond_ts (eg_pr eg) (eg_po eg) pre post in + let concl1 = f_forall_mems_ts_inv mprl mprr cond1 in + let concl2 = f_forall_mems_ts_inv mpol mpor cond2 in let concl3 = f_eagerF pre eg.eg_sl eg.eg_fl eg.eg_fr eg.eg_sr post in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_equivS_conseq pre post tc = let es = tc1_as_equivS tc in - let cond1, cond2 = conseq_cond es.es_pr es.es_po pre post in - let concl1 = f_forall_mems [es.es_ml;es.es_mr] cond1 in - let concl2 = f_forall_mems [es.es_ml;es.es_mr] cond2 in - let concl3 = f_equivS_r { es with es_pr = pre; es_po = post } in + let pre = ts_inv_rebind pre (fst es.es_ml) (fst es.es_mr) in + let post = ts_inv_rebind post (fst es.es_ml) (fst es.es_mr) in + let cond1, cond2 = conseq_cond_ts (es_pr es) (es_po es) pre post in + let concl1 = f_forall_mems_ts_inv es.es_ml es.es_mr cond1 in + let concl2 = f_forall_mems_ts_inv es.es_ml es.es_mr cond2 in + let concl3 = f_equivS (snd es.es_ml) (snd es.es_mr) pre es.es_sl es.es_sr post in FApi.xmutate1 tc `HlConseq [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_conseq pre post tc = - match (FApi.tc1_goal tc).f_node with - | FhoareF _ -> t_hoareF_conseq pre post tc - | FhoareS _ -> t_hoareS_conseq pre post tc - | FbdHoareF _ -> t_bdHoareF_conseq pre post tc - | FbdHoareS _ -> t_bdHoareS_conseq pre post tc - | FeHoareF _ -> t_ehoareF_conseq pre post tc - | FeHoareS _ -> t_ehoareS_conseq pre post tc - | FequivF _ -> t_equivF_conseq pre post tc - | FequivS _ -> t_equivS_conseq pre post tc - | FeagerF _ -> t_eagerF_conseq pre post tc + match (FApi.tc1_goal tc).f_node, pre, post with + | FhoareF _, Inv_ss pre, Inv_ss post -> t_hoareF_conseq pre post tc + | FhoareS _, Inv_ss pre, Inv_ss post -> t_hoareS_conseq pre post tc + | FbdHoareF _, Inv_ss pre, Inv_ss post -> t_bdHoareF_conseq pre post tc + | FbdHoareS _, Inv_ss pre, Inv_ss post -> t_bdHoareS_conseq pre post tc + | FeHoareF _ , Inv_ss pre, Inv_ss post -> t_ehoareF_conseq pre post tc + | FeHoareS _ , Inv_ss pre, Inv_ss post -> t_ehoareS_conseq pre post tc + | FequivF _ , Inv_ts pre, Inv_ts post -> t_equivF_conseq pre post tc + | FequivS _ , Inv_ts pre, Inv_ts post -> t_equivS_conseq pre post tc + | FeagerF _ , Inv_ts pre, Inv_ts post -> t_eagerF_conseq pre post tc | _ -> tc_error_noXhl !!tc (* -------------------------------------------------------------------- *) @@ -191,11 +218,11 @@ let mk_bind_glob env m (id,_) x = id, NormMp.norm_glob env m x let mk_bind_pvars m (bd1,bd2) = List.map2 (mk_bind_pvar m) bd1 bd2 let mk_bind_globs env m (bd1,bd2) = List.map2 (mk_bind_glob env m) bd1 bd2 -let cond_equivF_notmod ?(mk_other=false) tc cond = +let cond_equivF_notmod ?(mk_other=false) tc (cond: ts_inv) = let (env, hyps, _) = FApi.tc1_eflat tc in let ef = tc1_as_equivF tc in let fl, fr = ef.ef_fl, ef.ef_fr in - let (mprl,mprr),(mpol,mpor) = Fun.equivF_memenv fl fr env in + let (mprl,mprr),(mpol,mpor) = Fun.equivF_memenv ef.ef_ml ef.ef_mr fl fr env in let fsigl = (Fun.by_xpath fl env).f_sig in let fsigr = (Fun.by_xpath fr env).f_sig in let pvresl = pv_res and pvresr = pv_res in @@ -204,18 +231,19 @@ let cond_equivF_notmod ?(mk_other=false) tc cond = let fresl = f_local vresl fsigl.fs_ret in let fresr = f_local vresr fsigr.fs_ret in let ml, mr = fst mpol, fst mpor in + assert (ml = cond.ml && mr = cond.mr); let s = PVM.add env pvresl ml fresl (PVM.add env pvresr mr fresr PVM.empty) in - let cond = PVM.subst env s cond in + let cond = map_ts_inv1 (PVM.subst env s) cond in let modil, modir = f_write env fl, f_write env fr in - let cond, bdgr, bder = generalize_mod_ env mr modir cond in - let cond, bdgl, bdel = generalize_mod_ env ml modil cond in + let cond, bdgr, bder = generalize_mod_right_ env modir cond in + let cond, bdgl, bdel = generalize_mod_left_ env modil cond in let cond = - f_forall_simpl + map_ts_inv1 (f_forall_simpl [(vresl, GTty fsigl.fs_ret); - (vresr, GTty fsigr.fs_ret)] + (vresr, GTty fsigr.fs_ret)]) cond in assert (fst mprl = ml && fst mprr = mr); - let cond = f_forall_mems [mprl; mprr] (f_imp ef.ef_pr cond) in + let cond = f_forall_mems_ts_inv mprl mprr (map_ts_inv2 f_imp (ef_pr ef) cond) in let bmem = [ml;mr] in let bother = if mk_other then @@ -228,8 +256,9 @@ let cond_equivF_notmod ?(mk_other=false) tc cond = let t_equivF_notmod post tc = let ef = tc1_as_equivF tc in - let cond1, _, _ = cond_equivF_notmod tc (f_imp post ef.ef_po) in - let cond2 = f_equivF_r {ef with ef_po = post } in + let post = ts_inv_rebind post ef.ef_ml ef.ef_mr in + let cond1, _, _ = cond_equivF_notmod tc (map_ts_inv2 f_imp post (ef_po ef)) in + let cond2 = f_equivF (ef_pr ef) ef.ef_fl ef.ef_fr post in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) @@ -238,10 +267,11 @@ let cond_equivS_notmod ?(mk_other=false) tc cond = let es = tc1_as_equivS tc in let sl, sr = es.es_sl, es.es_sr in let ml, mr = fst es.es_ml, fst es.es_mr in + assert (ml = cond.ml && mr = cond.mr); let modil, modir = s_write env sl, s_write env sr in - let cond, bdgr, bder = generalize_mod_ env mr modir cond in - let cond, bdgl, bdel = generalize_mod_ env ml modil cond in - let cond = f_forall_mems [es.es_ml; es.es_mr] (f_imp es.es_pr cond) in + let cond, bdgr, bder = generalize_mod_right_ env modir cond in + let cond, bdgl, bdel = generalize_mod_left_ env modil cond in + let cond = f_forall_mems_ts_inv es.es_ml es.es_mr (map_ts_inv2 f_imp (es_pr es) cond) in let bmem = [ml;mr] in let bother = if mk_other then @@ -252,28 +282,28 @@ let cond_equivS_notmod ?(mk_other=false) tc cond = let t_equivS_notmod post tc = let es = tc1_as_equivS tc in - let cond1,_,_ = cond_equivS_notmod tc (f_imp post es.es_po) in - let cond2 = f_equivS_r {es with es_po = post} in + let post = ts_inv_rebind post (fst es.es_ml) (fst es.es_mr) in + let cond1,_,_ = cond_equivS_notmod tc (map_ts_inv2 f_imp post (es_po es)) in + let cond2 = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) es.es_sl es.es_sr post in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) -let cond_hoareF_notmod ?(mk_other=false) tc cond = +let cond_hoareF_notmod ?(mk_other=false) tc (cond: ss_inv) = let (env, hyps, _) = FApi.tc1_eflat tc in let hf = tc1_as_hoareF tc in let f = hf.hf_f in - let mpr,mpo = Fun.hoareF_memenv f env in + let mpr,mpo = Fun.hoareF_memenv hf.hf_m f env in let fsig = (Fun.by_xpath f env).f_sig in let pvres = pv_res in let vres = LDecl.fresh_id hyps "result" in let fres = f_local vres fsig.fs_ret in let m = fst mpo in let s = PVM.add env pvres m fres PVM.empty in - let cond = PVM.subst env s cond in + let cond = map_ss_inv1 (PVM.subst env s) cond in let modi = f_write env f in - let cond,bdg,bde = generalize_mod_ env m modi cond in - let cond = f_forall_simpl [(vres, GTty fsig.fs_ret)] cond in - assert (fst mpr = m); - let cond = f_forall_mems [mpr] (f_imp hf.hf_pr cond) in + let cond,bdg,bde = generalize_mod_ env modi cond in + let cond = map_ss_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) cond in + let cond = f_forall_mems_ss_inv mpr (map_ss_inv2 f_imp (hf_pr hf) cond) in let bmem = [m] in let bother = if mk_other then @@ -282,10 +312,11 @@ let cond_hoareF_notmod ?(mk_other=false) tc cond = else [] in cond, bmem, bother -let t_hoareF_notmod post tc = +let t_hoareF_notmod (post: ss_inv) tc = let hf = tc1_as_hoareF tc in - let cond1, _, _ = cond_hoareF_notmod tc (f_imp post hf.hf_po) in - let cond2 = f_hoareF_r { hf with hf_po = post } in + let post = ss_inv_rebind post hf.hf_m in + let cond1, _, _ = cond_hoareF_notmod tc (map_ss_inv2 f_imp post (hf_po hf)) in + let cond2 = f_hoareF (hf_pr hf) hf.hf_f post in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) @@ -295,8 +326,8 @@ let cond_hoareS_notmod ?(mk_other=false) tc cond = let s = hs.hs_s in let m = fst hs.hs_m in let modi = s_write env s in - let cond, bdg, bde = generalize_mod_ env m modi cond in - let cond = f_forall_mems [hs.hs_m] (f_imp hs.hs_pr cond) in + let cond, bdg, bde = generalize_mod_ env modi cond in + let cond = f_forall_mems_ss_inv hs.hs_m (map_ss_inv2 f_imp (hs_pr hs) cond) in let bmem = [m] in let bother = if mk_other then @@ -306,28 +337,29 @@ let cond_hoareS_notmod ?(mk_other=false) tc cond = let t_hoareS_notmod post tc = let hs = tc1_as_hoareS tc in - let cond1, _, _ = cond_hoareS_notmod tc (f_imp post hs.hs_po) in - let cond2 = f_hoareS_r {hs with hs_po = post} in + let post = ss_inv_rebind post (fst hs.hs_m) in + let cond1, _, _ = cond_hoareS_notmod tc (map_ss_inv2 f_imp post (hs_po hs)) in + let cond2 = f_hoareS (snd hs.hs_m) (hs_pr hs) hs.hs_s post in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) -let cond_bdHoareF_notmod ?(mk_other=false) tc cond = +let cond_bdHoareF_notmod ?(mk_other=false) tc (cond: ss_inv) = let (env, hyps, _) = FApi.tc1_eflat tc in let hf = tc1_as_bdhoareF tc in let f = hf.bhf_f in - let mpr,mpo = Fun.hoareF_memenv f env in + let mpr,mpo = Fun.hoareF_memenv hf.bhf_m f env in let fsig = (Fun.by_xpath f env).f_sig in let pvres = pv_res in let vres = LDecl.fresh_id hyps "result" in let fres = f_local vres fsig.fs_ret in let m = fst mpo in let s = PVM.add env pvres m fres PVM.empty in - let cond = PVM.subst env s cond in + let cond = map_ss_inv1 (PVM.subst env s) cond in let modi = f_write env f in - let cond, bdg, bde = generalize_mod_ env m modi cond in - let cond = f_forall_simpl [(vres, GTty fsig.fs_ret)] cond in + let cond, bdg, bde = generalize_mod_ env modi cond in + let cond = map_ss_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) cond in assert (fst mpr = m); - let cond = f_forall_mems [mpr] (f_imp hf.bhf_pr cond) in + let cond = f_forall_mems_ss_inv mpr (map_ss_inv2 f_imp (bhf_pr hf) cond) in let bmem = [m] in let bother = if mk_other then @@ -339,21 +371,22 @@ let cond_bdHoareF_notmod ?(mk_other=false) tc cond = let t_bdHoareF_notmod post tc = let hf = tc1_as_bdhoareF tc in + let post = ss_inv_rebind post hf.bhf_m in let _, cond = - bdHoare_conseq_conds hf.bhf_cmp hf.bhf_pr hf.bhf_po hf.bhf_pr post in + bdHoare_conseq_conds hf.bhf_cmp (bhf_pr hf) (bhf_po hf) (bhf_pr hf) post in let cond1, _, _ = cond_bdHoareF_notmod tc cond in - let cond2 = f_bdHoareF_r {hf with bhf_po = post} in + let cond2 = f_bdHoareF (bhf_pr hf) hf.bhf_f post hf.bhf_cmp (bhf_bd hf) in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) -let cond_bdHoareS_notmod ?(mk_other=false) tc cond = +let cond_bdHoareS_notmod ?(mk_other=false) tc (cond: ss_inv) = let env = FApi.tc1_env tc in let hs = tc1_as_bdhoareS tc in let s = hs.bhs_s in let m = fst hs.bhs_m in let modi = s_write env s in - let cond, bdg, bde = generalize_mod_ env m modi cond in - let cond = f_forall_mems [hs.bhs_m] (f_imp hs.bhs_pr cond) in + let cond, bdg, bde = generalize_mod_ env modi cond in + let cond = f_forall_mems_ss_inv hs.bhs_m (map_ss_inv2 f_imp (bhs_pr hs) cond) in let bmem = [m] in let bother = if mk_other then @@ -363,10 +396,11 @@ let cond_bdHoareS_notmod ?(mk_other=false) tc cond = let t_bdHoareS_notmod post tc = let hs = tc1_as_bdhoareS tc in + let post = ss_inv_rebind post (fst hs.bhs_m) in let _, cond = - bdHoare_conseq_conds hs.bhs_cmp hs.bhs_pr hs.bhs_po hs.bhs_pr post in + bdHoare_conseq_conds hs.bhs_cmp (bhs_pr hs) (bhs_po hs) (bhs_pr hs) post in let cond1, _, _ = cond_bdHoareS_notmod tc cond in - let cond2 = f_bdHoareS_r {hs with bhs_po = post} in + let cond2 = f_bdHoareS (snd hs.bhs_m) (bhs_pr hs) hs.bhs_s post hs.bhs_cmp (bhs_bd hs) in FApi.xmutate1 tc `HlNotmod [cond1; cond2] (* -------------------------------------------------------------------- *) @@ -379,9 +413,27 @@ let gen_conseq_nm tnm tc pre post = FApi.t_swap_goals 0 1 gs ) -let t_hoareF_conseq_nm = gen_conseq_nm t_hoareF_notmod t_hoareF_conseq +let gen_conseq_nm_ss tnm tc (pre: ss_inv) (post: ss_inv) = + FApi.t_internal ~info:"generic-conseq-nm" (fun g -> + let gs = + (tnm post @+ + [ t_id; + tc pre post @+ [t_id; t_trivial; t_id] ]) g in + FApi.t_swap_goals 0 1 gs + ) + +let gen_conseq_nm_ts tnm tc (pre: ts_inv) (post: ts_inv) = + FApi.t_internal ~info:"generic-conseq-nm" (fun g -> + let gs = + (tnm post @+ + [ t_id; + tc pre post @+ [t_id; t_trivial; t_id] ]) g in + FApi.t_swap_goals 0 1 gs + ) + +let t_hoareF_conseq_nm = gen_conseq_nm_ss t_hoareF_notmod t_hoareF_conseq let t_hoareS_conseq_nm = gen_conseq_nm t_hoareS_notmod t_hoareS_conseq -let t_equivF_conseq_nm = gen_conseq_nm t_equivF_notmod t_equivF_conseq +let t_equivF_conseq_nm = gen_conseq_nm_ts t_equivF_notmod t_equivF_conseq let t_equivS_conseq_nm = gen_conseq_nm t_equivS_notmod t_equivS_conseq let t_bdHoareF_conseq_nm = gen_conseq_nm t_bdHoareF_notmod t_bdHoareF_conseq let t_bdHoareS_conseq_nm = gen_conseq_nm t_bdHoareS_notmod t_bdHoareS_conseq @@ -394,33 +446,35 @@ let t_bdHoareS_conseq_nm = gen_conseq_nm t_bdHoareS_notmod t_bdHoareS_conseq {f g1} c { f g2 } *) -let t_ehoareF_concave fc pre post tc = +let t_ehoareF_concave (fc: ss_inv) pre post tc = let env = FApi.tc1_env tc in let hf = tc1_as_ehoareF tc in let f = hf.ehf_f in - let mpr,mpo = Fun.hoareF_memenv f env in + let mpr,mpo = Fun.hoareF_memenv hf.ehf_m f env in let fsig = (Fun.by_xpath f env).f_sig in let m = fst mpo in assert (fst mpr = m && fst mpo = m); (* ensure that f only depend of notmod *) let modi = f_write env f in let modi = PV.add env pv_res fsig.fs_ret modi in - let fv = PV.fv env m fc in + let fv = PV.fv env m fc.inv in let inter = PV.interdep env fv modi in if not (PV.is_empty inter) then tc_error !!tc "the function should not depend on modified elements: %a" (PV.pp env) inter; let g0 = - f_forall_mems [EcMemory.empty_local ~witharg:false m] (f_concave_incr fc) in + f_forall_mems_ss_inv (EcMemory.empty_local ~witharg:false m) (map_ss_inv1 f_concave_incr fc) in let g1 = - let cond = f_xreal_le (f_app_simpl fc [pre] txreal) hf.ehf_pr in - f_forall_mems [mpr] cond in + let cond = map_ss_inv2 (fun pre fc -> f_app_simpl fc [pre] txreal) pre fc in + let cond = map_ss_inv2 f_xreal_le cond (ehf_pr hf) in + f_forall_mems_ss_inv mpr cond in let g2 = - let cond = f_xreal_le hf.ehf_po (f_app_simpl fc [post] txreal) in - f_forall_mems [mpo] cond in + let cond = map_ss_inv2 (fun post fc -> f_app_simpl fc [post] txreal) post fc in + let cond = map_ss_inv2 f_xreal_le (ehf_po hf) cond in + f_forall_mems_ss_inv mpo cond in let g3 = f_eHoareF pre f post in @@ -428,32 +482,34 @@ let t_ehoareF_concave fc pre post tc = FApi.xmutate1 tc `HlConseq [g0; g1; g2; g3] (* -------------------------------------------------------------------- *) -let t_ehoareS_concave fc (* xreal -> xreal *) pre post tc = +let t_ehoareS_concave (fc: ss_inv) (* xreal -> xreal *) pre post tc = let env = FApi.tc1_env tc in let hs = tc1_as_ehoareS tc in let s = hs.ehs_s in let m = fst hs.ehs_m in (* ensure that f only depend of notmod *) let modi = s_write env s in - let fv = PV.fv env m fc in + let fv = PV.fv env m fc.inv in let inter = PV.interdep env fv modi in if not (PV.is_empty inter) then tc_error !!tc "the function should not depend on modified elements: %a" (PV.pp env) inter; let g0 = - f_forall_mems [hs.ehs_m] (f_concave_incr fc) in + f_forall_mems_ss_inv hs.ehs_m (map_ss_inv1 f_concave_incr fc) in let g1 = - let cond = f_xreal_le (f_app_simpl fc [pre] txreal) hs.ehs_pr in - f_forall_mems [hs.ehs_m] cond in + let cond = map_ss_inv2 (fun pre fc -> f_app_simpl fc [pre] txreal) pre fc in + let cond = map_ss_inv2 f_xreal_le cond (ehs_pr hs) in + f_forall_mems_ss_inv hs.ehs_m cond in let g2 = - let cond = f_xreal_le hs.ehs_po (f_app_simpl fc [post] txreal) in - f_forall_mems [hs.ehs_m] cond in + let cond = map_ss_inv2 (fun post fc -> f_app_simpl fc [post] txreal) post fc in + let cond = map_ss_inv2 f_xreal_le (ehs_po hs) cond in + f_forall_mems_ss_inv hs.ehs_m cond in let g3 = - f_eHoareS hs.ehs_m pre s post in + f_eHoareS (snd hs.ehs_m) pre s post in FApi.xmutate1 tc `HlConseq [g0; g1; g2; g3] @@ -475,24 +531,26 @@ let t_ehoareF_conseq_nm pre post tc = let (env, hyps, _) = FApi.tc1_eflat tc in let hf = tc1_as_ehoareF tc in let f = hf.ehf_f in - let _mpr,mpo = Fun.hoareF_memenv f env in + let _mpr,mpo = Fun.hoareF_memenv hf.ehf_m f env in let fsig = (Fun.by_xpath f env).f_sig in - let _cond1, cond2 = conseq_econd hf.ehf_pr hf.ehf_po pre post in + let _cond1, cond2 = conseq_econd (ehf_pr hf) (ehf_po hf) pre post in let pvres = pv_res in let vres = LDecl.fresh_id hyps "result" in let fres = f_local vres fsig.fs_ret in let m = fst mpo in let s = PVM.add env pvres m fres PVM.empty in - let cond = PVM.subst env s cond2 in + let cond = map_ss_inv1 (PVM.subst env s) cond2 in let modi = f_write env f in - let cond,_,_ = generalize_mod_ env m modi cond in - let cond = f_forall_simpl [(vres, GTty fsig.fs_ret)] cond in + let cond,_,_ = generalize_mod_ env modi cond in + let cond = map_ss_inv1 (f_forall_simpl [(vres, GTty fsig.fs_ret)]) cond in let fc = let x = EcIdent.create "x" in - f_lambda [x,GTty txreal] (f_interp_ehoare_form cond (f_local x txreal)) in + let f_interp_ehoare_form' cond = + f_interp_ehoare_form cond (f_local x txreal) in + map_ss_inv1 (fun cd -> f_lambda [x,GTty txreal] (f_interp_ehoare_form' cd)) cond in (t_ehoareF_concave fc pre post @+ t_ehoare_conseq_nm_end) tc @@ -501,14 +559,14 @@ let t_ehoareS_conseq_nm pre post tc = let env = FApi.tc1_env tc in let hs = tc1_as_ehoareS tc in let s = hs.ehs_s in - let m = fst hs.ehs_m in let modi = s_write env s in - let _cond1, cond2 = conseq_econd hs.ehs_pr hs.ehs_po pre post in - let cond, _bdg, _bde = generalize_mod_ env m modi cond2 in - + let _cond1, cond2 = conseq_econd (ehs_pr hs) (ehs_po hs) pre post in + let cond, _bdg, _bde = generalize_mod_ env modi cond2 in let fc = let x = EcIdent.create "x" in - f_lambda [x,GTty txreal] (f_interp_ehoare_form cond (f_local x txreal)) in + let f_interp_ehoare_form' cond = + f_interp_ehoare_form cond (f_local x txreal) in + map_ss_inv1 (fun cond -> f_lambda [x,GTty txreal] (f_interp_ehoare_form' cond)) cond in (t_ehoareS_concave fc pre post @+ t_ehoare_conseq_nm_end) tc @@ -521,12 +579,14 @@ let process_concave ((info, fc) : pformula option tuple2 gppterm * pformula) tc let fc = match concl.f_node with | FeHoareS hs -> - let env = LDecl.push_active hs.ehs_m hyps in - TTC.pf_process_form !!tc env (tfun txreal txreal) fc + let m = fst hs.ehs_m in + let env = LDecl.push_active_ss hs.ehs_m hyps in + {m; inv=TTC.pf_process_form !!tc env (tfun txreal txreal) fc} | FeHoareF hf -> - let _, env = LDecl.hoareF hf.ehf_f hyps in - TTC.pf_process_form !!tc env (tfun txreal txreal) fc + let m = hf.ehf_m in + let _, env = LDecl.hoareF hf.ehf_m hf.ehf_f hyps in + {m; inv=TTC.pf_process_form !!tc env (tfun txreal txreal) fc} | _ -> tc_error !!tc "conseq concave: not a ehoare judgement" in @@ -535,21 +595,22 @@ let process_concave ((info, fc) : pformula option tuple2 gppterm * pformula) tc let penv, qenv, gpre, gpost, fmake = match concl.f_node with | FeHoareS hs -> - let env = LDecl.push_active hs.ehs_m hyps in - let fmake pre post = f_eHoareS_r { hs with ehs_pr = pre; ehs_po = post; } in - (env, env, hs.ehs_pr, hs.ehs_po, fmake) + let env = LDecl.push_active_ss hs.ehs_m hyps in + let fmake pre post = f_eHoareS (snd hs.ehs_m) pre hs.ehs_s post in + (env, env, (ehs_pr hs), (ehs_po hs), fmake) | FeHoareF hf -> - let penv, qenv = LDecl.hoareF hf.ehf_f hyps in + let penv, qenv = LDecl.hoareF hf.ehf_m hf.ehf_f hyps in let fmake pre post = - f_eHoareF_r { hf with ehf_pr = pre; ehf_po = post } in - (penv, qenv, hf.ehf_pr, hf.ehf_po, fmake) + f_eHoareF pre hf.ehf_f post in + (penv, qenv, (ehf_pr hf), (ehf_po hf), fmake) | _ -> tc_error !!tc "conseq concave: not a ehoare judgement" in - let pre = pre |> omap (TTC.pf_process_form !!tc penv txreal) |> odfl gpre in - let post = post |> omap (TTC.pf_process_form !!tc qenv txreal) |> odfl gpost in + let pre = map_ss_inv1 (fun gpre -> pre |> omap (TTC.pf_process_form !!tc penv txreal) |> odfl gpre) gpre in + let post = map_ss_inv1 (fun gpost -> post |> omap (TTC.pf_process_form !!tc qenv txreal) |> odfl gpost) gpost in + fmake pre post in @@ -563,11 +624,11 @@ let process_concave ((info, fc) : pformula option tuple2 gppterm * pformula) tc match (snd f1).f_node with | FeHoareS hs -> FApi.t_first t_concave_incr - (FApi.t_on1seq 3 (t_ehoareS_concave fc hs.ehs_pr hs.ehs_po) t_apply_r tc) + (FApi.t_on1seq 3 (t_ehoareS_concave fc (ehs_pr hs) (ehs_po hs)) t_apply_r tc) | FeHoareF hf -> FApi.t_first t_concave_incr - (FApi.t_on1seq 3 (t_ehoareF_concave fc hf.ehf_pr hf.ehf_po) t_apply_r tc) + (FApi.t_on1seq 3 (t_ehoareF_concave fc (ehf_pr hf) (ehf_po hf)) t_apply_r tc) | _ -> tc_error !!tc "conseq concave: not a ehoare judgement" @@ -583,90 +644,105 @@ let process_concave ((info, fc) : pformula option tuple2 gppterm * pformula) tc (* -------------------------------------------------------------------- *) let t_hoareS_conseq_bdhoare tc = let hs = tc1_as_hoareS tc in - let concl1 = f_bdHoareS hs.hs_m hs.hs_pr hs.hs_s hs.hs_po FHeq f_r1 in + let f_r1 = {m=fst hs.hs_m; inv=f_r1} in + let concl1 = f_bdHoareS (snd hs.hs_m) (hs_pr hs) hs.hs_s (hs_po hs) FHeq f_r1 in FApi.xmutate1 tc `HlConseqBd [concl1] (* -------------------------------------------------------------------- *) let t_hoareF_conseq_bdhoare tc = let hf = tc1_as_hoareF tc in - let concl1 = f_bdHoareF hf.hf_pr hf.hf_f hf.hf_po FHeq f_r1 in + let f_r1 = {m=hf.hf_m; inv=f_r1} in + let concl1 = f_bdHoareF (hf_pr hf) hf.hf_f (hf_po hf) FHeq f_r1 in FApi.xmutate1 tc `HlConseqBd [concl1] (* -------------------------------------------------------------------- *) let t_hoareS_conseq_conj pre post pre' post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let hs = tc1_as_hoareS tc in - if not (f_equal hs.hs_pr (f_and pre' pre)) then - tc_error !!tc "invalid pre-condition"; - if not (f_equal hs.hs_po (f_and post' post)) then - tc_error !!tc "invalid post-condition"; - let concl1 = f_hoareS_r { hs with hs_pr = pre; hs_po = post } in - let concl2 = f_hoareS_r { hs with hs_pr = pre'; hs_po = post' } in + let pre'' = map_ss_inv2 f_and pre' pre in + let post' = map_ss_inv2 f_and post' post in + if not (ss_inv_alpha_eq hyps (hs_pr hs) pre'') + then tc_error !!tc "invalid pre-condition"; + if not (ss_inv_alpha_eq hyps (hs_po hs) post') + then tc_error !!tc "invalid post-condition"; + let concl1 = f_hoareS (snd hs.hs_m) pre hs.hs_s post in + let concl2 = f_hoareS (snd hs.hs_m) pre' hs.hs_s post' in FApi.xmutate1 tc `HlConseqBd [concl1; concl2] (* -------------------------------------------------------------------- *) let t_hoareF_conseq_conj pre post pre' post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let hf = tc1_as_hoareF tc in - if not (f_equal hf.hf_pr (f_and pre' pre)) then - tc_error !!tc "invalid pre-condition"; - if not (f_equal hf.hf_po (f_and post' post)) then - tc_error !!tc "invalid post-condition"; + let pre'' = map_ss_inv2 f_and pre' pre in + let post'' = map_ss_inv2 f_and post' post in + if not (ss_inv_alpha_eq hyps (hf_pr hf) pre'') + then tc_error !!tc "invalid pre-condition"; + if not (ss_inv_alpha_eq hyps (hf_po hf) post'') + then tc_error !!tc "invalid post-condition"; let concl1 = f_hoareF pre hf.hf_f post in let concl2 = f_hoareF pre' hf.hf_f post' in FApi.xmutate1 tc `HlConseqBd [concl1; concl2] (* -------------------------------------------------------------------- *) let t_bdHoareS_conseq_conj ~add post post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let hs = tc1_as_bdhoareS tc in - let postc = if add then f_and post' post else post' in - let posth = if add then post' else f_and post' post in - if not (f_equal hs.bhs_po postc) then + let postc = if add then map_ss_inv2 f_and post' post else post' in + let posth = if add then post' else map_ss_inv2 f_and post' post in + if not (ss_inv_alpha_eq hyps (bhs_po hs) postc) then tc_error !!tc "invalid post-condition"; - let concl1 = f_hoareS hs.bhs_m hs.bhs_pr hs.bhs_s post in - let concl2 = f_bdHoareS_r { hs with bhs_po = posth } in + let concl1 = f_hoareS (snd hs.bhs_m) (bhs_pr hs) hs.bhs_s post in + let concl2 = f_bdHoareS (snd hs.bhs_m) (bhs_pr hs) hs.bhs_s posth + hs.bhs_cmp (bhs_bd hs) in FApi.xmutate1 tc `HlConseqBd [concl1; concl2] (* -------------------------------------------------------------------- *) let t_bdHoareF_conseq_conj ~add post post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let hs = tc1_as_bdhoareF tc in - let postc = if add then f_and post' post else post' in - let posth = if add then post' else f_and post' post in - if not (f_equal hs.bhf_po postc) then + let post = ss_inv_rebind post hs.bhf_m in + let post' = ss_inv_rebind post' hs.bhf_m in + let postc = if add then map_ss_inv2 f_and post' post else post' in + let posth = if add then post' else map_ss_inv2 f_and post' post in + if not (ss_inv_alpha_eq hyps (bhf_po hs) postc) then tc_error !!tc "invalid post-condition"; - let concl1 = f_hoareF hs.bhf_pr hs.bhf_f post in - let concl2 = f_bdHoareF_r { hs with bhf_po = posth } in + let concl1 = f_hoareF (bhf_pr hs) hs.bhf_f post in + let concl2 = f_bdHoareF (bhf_pr hs) hs.bhf_f posth hs.bhf_cmp (bhf_bd hs) in FApi.xmutate1 tc `HlConseqBd [concl1; concl2] (* -------------------------------------------------------------------- *) let t_equivS_conseq_conj pre1 post1 pre2 post2 pre' post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let es = tc1_as_equivS tc in - let subst1 = Fsubst.f_subst_mem mhr mleft in - let subst2 = Fsubst.f_subst_mem mhr mright in - let pre1' = subst1 pre1 in - let post1' = subst1 post1 in - let pre2' = subst2 pre2 in - let post2' = subst2 post2 in - if not (f_equal es.es_pr (f_ands [pre';pre1';pre2'])) then + let (ml, mtl), (mr, mtr) = es.es_ml, es.es_mr in + let pre1' = ss_inv_generalize_right (ss_inv_rebind pre1 ml) mr in + let post1' = ss_inv_generalize_right (ss_inv_rebind post1 ml) mr in + let pre2' = ss_inv_generalize_left (ss_inv_rebind pre2 mr) ml in + let post2' = ss_inv_generalize_left (ss_inv_rebind post2 mr) ml in + if not (ts_inv_alpha_eq hyps (es_pr es) (map_ts_inv f_ands [pre';pre1';pre2'])) then tc_error !!tc "invalid pre-condition"; - if not (f_equal es.es_po (f_ands [post';post1';post2'])) then + if not (ts_inv_alpha_eq hyps (es_po es) (map_ts_inv f_ands [post';post1';post2'])) then tc_error !!tc "invalid post-condition"; - let concl1 = f_hoareS (mhr,snd es.es_ml) pre1 es.es_sl post1 in - let concl2 = f_hoareS (mhr,snd es.es_mr) pre2 es.es_sr post2 in - let concl3 = f_equivS_r {es with es_pr = pre'; es_po = post'} in + let concl1 = f_hoareS mtl pre1 es.es_sl post1 in + let concl2 = f_hoareS mtr pre2 es.es_sr post2 in + let concl3 = f_equivS mtl mtr pre' es.es_sl es.es_sr post' in FApi.xmutate1 tc `HlConseqConj [concl1; concl2; concl3] (* -------------------------------------------------------------------- *) let t_equivF_conseq_conj pre1 post1 pre2 post2 pre' post' tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let ef = tc1_as_equivF tc in - let subst1 = Fsubst.f_subst_mem mhr mleft in - let subst2 = Fsubst.f_subst_mem mhr mright in - let pre1' = subst1 pre1 in - let post1' = subst1 post1 in - let pre2' = subst2 pre2 in - let post2' = subst2 post2 in - if not (f_equal ef.ef_pr (f_ands [pre';pre1';pre2']) ) then - tc_error !!tc "invalid pre-condition"; - if not (f_equal ef.ef_po (f_ands [post';post1';post2'])) then - tc_error !!tc "invalid post-condition"; + let ml, mr = ef.ef_ml, ef.ef_mr in + let pre1' = ss_inv_generalize_right (ss_inv_rebind pre1 ml) mr in + let post1' = ss_inv_generalize_right (ss_inv_rebind post1 ml) mr in + let pre2' = ss_inv_generalize_left (ss_inv_rebind pre2 mr) ml in + let post2' = ss_inv_generalize_left (ss_inv_rebind post2 mr) ml in + let pre'' = map_ts_inv f_ands [pre'; pre1'; pre2'] in + let post'' = map_ts_inv f_ands [post'; post1'; post2'] in + if not (ts_inv_alpha_eq hyps (ef_pr ef) pre'') + then tc_error !!tc "invalid pre-condition"; + if not (ts_inv_alpha_eq hyps (ef_po ef) post'') + then tc_error !!tc "invalid post-condition"; let concl1 = f_hoareF pre1 ef.ef_fl post1 in let concl2 = f_hoareF pre2 ef.ef_fr post2 in let concl3 = f_equivF pre' ef.ef_fl ef.ef_fr post' in @@ -674,21 +750,30 @@ let t_equivF_conseq_conj pre1 post1 pre2 post2 pre' post' tc = (* -------------------------------------------------------------------- *) let t_equivS_conseq_bd side pr po tc = + let (_, hyps, _) = FApi.tc1_eflat tc in let es = tc1_as_equivS tc in - let m,s,s' = + let ((ml,_), (mr,_)) = es.es_ml, es.es_mr in + let m,s,s',prs,pos = match side with - | `Left -> es.es_ml, es.es_sl, es.es_sr - | `Right -> es.es_mr, es.es_sr, es.es_sl + | `Left -> + let pos = ss_inv_generalize_right (ss_inv_rebind po ml) mr in + let prs = ss_inv_generalize_right (ss_inv_rebind pr ml) mr in + es.es_ml, es.es_sl, es.es_sr, prs, pos + | `Right -> + let pos = ss_inv_generalize_left (ss_inv_rebind po mr) ml in + let prs = ss_inv_generalize_left (ss_inv_rebind pr mr) ml in + es.es_mr, es.es_sr, es.es_sl, prs, pos in if not (List.is_empty s'.s_node) then begin let side = side2str (negside side) in tc_error !!tc "%s statement should be empty" side end; - let subst = Fsubst.f_subst_mem mhr (fst m) in - let prs, pos = subst pr, subst po in - if not (f_equal prs es.es_pr && f_equal pos es.es_po) then + if not (ts_inv_alpha_eq hyps prs (es_pr es)) then tc_error !!tc "invalid pre- or post-condition"; - let g1 = f_bdHoareS (mhr,snd m) pr s po FHeq f_r1 in + if not (ts_inv_alpha_eq hyps pos (es_po es)) then + tc_error !!tc "invalid pre- or post-condition"; + let f_r1 = {m=fst m; inv=f_r1} in + let g1 = f_bdHoareS (snd m) pr s po FHeq f_r1 in FApi.xmutate1 tc `HlBdEquiv [g1] (* -------------------------------------------------------------------- *) @@ -704,20 +789,20 @@ hoare M1 : P1 ==> Q1. let transitivity_side_cond hyps prml poml pomr p q p2 q2 p1 q1 = let env = LDecl.toenv hyps in let cond1 = - let fv1 = PV.fv env mright p in - let fv2 = PV.fv env mhr p2 in + let fv1 = PV.fv env p.mr p.inv in + let fv2 = PV.fv env p2.m p2.inv in let fv = PV.union fv1 fv2 in let elts, glob = PV.ntr_elements fv in let bd, s = generalize_subst env mhr elts glob in let s1 = PVM.of_mpv s mright in let s2 = PVM.of_mpv s mhr in - let concl = f_and (PVM.subst env s1 p) (PVM.subst env s2 p2) in - let p1 = Fsubst.f_subst_mem mhr mleft p1 in - f_forall_mems [prml] (f_imp p1 (f_exists bd concl)) in + let concl = f_and (PVM.subst env s1 p.inv) (PVM.subst env s2 p2.inv) in + let p1 = ss_inv_rebind p1 p.ml in + f_forall_mems [prml] (f_imp p1.inv (f_exists bd concl)) in let cond2 = - let q1 = Fsubst.f_subst_mem mhr mleft q1 in - let q2 = Fsubst.f_subst_mem mhr mright q2 in - f_forall_mems [poml; pomr] (f_imps [q;q2] q1) in + let q1 = ss_inv_generalize_as_left q1 q.ml q.mr in + let q2 = ss_inv_generalize_as_right q2 q.ml q.mr in + f_forall_mems_ts_inv poml pomr (map_ts_inv3 (fun q q2 q1 -> f_imps [q;q2] q1) q q2 q1) in (cond1, cond2) let t_hoareF_conseq_equiv f2 p q p2 q2 tc = @@ -725,19 +810,19 @@ let t_hoareF_conseq_equiv f2 p q p2 q2 tc = let hf1 = tc1_as_hoareF tc in let ef = f_equivF p hf1.hf_f f2 q in let hf2 = f_hoareF p2 f2 q2 in - let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv hf1.hf_f f2 env in + let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv p.ml p.mr hf1.hf_f f2 env in let (cond1, cond2) = - transitivity_side_cond hyps prml poml pomr p q p2 q2 hf1.hf_pr hf1.hf_po in + transitivity_side_cond hyps prml poml pomr p q p2 q2 (hf_pr hf1) (hf_po hf1) in FApi.xmutate1 tc `HoareFConseqEquiv [cond1; cond2; ef; hf2] let t_bdHoareF_conseq_equiv f2 p q p2 q2 tc = let env, hyps, _ = FApi.tc1_eflat tc in let hf1 = tc1_as_bdhoareF tc in let ef = f_equivF p hf1.bhf_f f2 q in - let hf2 = f_bdHoareF p2 f2 q2 hf1.bhf_cmp hf1.bhf_bd in - let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv hf1.bhf_f f2 env in + let hf2 = f_bdHoareF p2 f2 q2 hf1.bhf_cmp (bhf_bd hf1) in + let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv p.ml p.mr hf1.bhf_f f2 env in let (cond1, cond2) = - transitivity_side_cond hyps prml poml pomr p q p2 q2 hf1.bhf_pr hf1.bhf_po in + transitivity_side_cond hyps prml poml pomr p q p2 q2 (bhf_pr hf1) (bhf_po hf1) in FApi.xmutate1 tc `BdHoareFConseqEquiv [cond1; cond2; ef; hf2] @@ -746,25 +831,27 @@ let t_ehoareF_conseq_equiv f2 p q p2 q2 tc = let hf1 = tc1_as_ehoareF tc in let ef = f_equivF p hf1.ehf_f f2 q in let hf2 = f_eHoareF p2 f2 q2 in - let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv hf1.ehf_f f2 env in - let p1 = hf1.ehf_pr and q1 = hf1.ehf_po in + let (prml, _prmr), (poml, pomr) = Fun.equivF_memenv p.ml p.mr hf1.ehf_f f2 env in + let p1 = (ehf_pr hf1) and q1 = (ehf_po hf1) in let cond1 = - let fv1 = PV.fv env mright p in - let fv2 = PV.fv env mhr p2 in + let fv1 = PV.fv env p.mr p.inv in + let fv2 = PV.fv env p2.m p2.inv in let fv = PV.union fv1 fv2 in let elts, glob = PV.ntr_elements fv in - let bd, s = generalize_subst env mhr elts glob in - let s1 = PVM.of_mpv s mright in - let s2 = PVM.of_mpv s mhr in - let p1 = Fsubst.f_subst_mem mhr mleft p1 in + let bd, s = generalize_subst env p2.m elts glob in + let s1 = PVM.of_mpv s p.mr in + let s2 = PVM.of_mpv s p2.m in + let p1 = ss_inv_rebind p1 p.ml in let concl = - f_or (f_eq p1 f_xreal_inf) - (f_and (PVM.subst env s1 p) (f_xreal_le (PVM.subst env s2 p2) p1)) in + f_or (f_eq p1.inv f_xreal_inf) + (f_and (PVM.subst env s1 p.inv) (f_xreal_le (PVM.subst env s2 p2.inv) p1.inv)) in f_forall_mems [prml] (f_exists bd concl) in let cond2 = - let q1 = Fsubst.f_subst_mem mhr mleft q1 in - let q2 = Fsubst.f_subst_mem mhr mright q2 in - f_forall_mems [poml; pomr] (f_imp q (f_xreal_le q1 q2)) in + let q1 = ss_inv_rebind q1 q.ml in + let q1 = ss_inv_generalize_right q1 q.mr in + let q2 = ss_inv_rebind q2 q.mr in + let q2 = ss_inv_generalize_left q2 q.ml in + f_forall_mems_ts_inv poml pomr (map_ts_inv3 (fun q q1 q2 -> f_imp q (f_xreal_le q1 q2)) q q1 q2) in FApi.xmutate1 tc `HoareFConseqEquiv [cond1; cond2; ef; hf2] @@ -804,7 +891,7 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = (* hoareS / hoareS / ⊥ / ⊥ *) | FhoareS _, Some ((_, {f_node = FhoareS hs}) as nf1), None, None -> let tac = if notmod then t_hoareS_conseq_nm else t_hoareS_conseq in - t_on1 2 (t_apply_r nf1) (tac hs.hs_pr hs.hs_po tc) + t_on1 2 (t_apply_r nf1) (tac (hs_pr hs) (hs_po hs) tc) (* ------------------------------------------------------------------ *) (* hoareS / hoareS / hoareS / ⊥ *) @@ -817,9 +904,10 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_hoareS_conseq_nm else t_hoareS_conseq in t_on1seq 2 - (tac (f_and hs.hs_pr hs2.hs_pr) (f_and hs.hs_po hs2.hs_po)) + (tac (map_ss_inv2 f_and (hs_pr hs) (hs_pr hs2)) + (map_ss_inv2 f_and (hs_po hs) (hs_po hs2))) (FApi.t_seqsub - (t_hoareS_conseq_conj hs2.hs_pr hs2.hs_po hs.hs_pr hs.hs_po) + (t_hoareS_conseq_conj (hs_pr hs2) (hs_po hs2) (hs_pr hs) (hs_po hs)) [t_apply_r nf2; t_apply_r nf1]) tc @@ -833,30 +921,34 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = FApi.t_seq t_hoareS_conseq_bdhoare (t_on1seq 1 - (t_bdHoareS_conseq_bd hs.bhs_cmp hs.bhs_bd) - (t_on1seq 2 (tac hs.bhs_pr hs.bhs_po) (t_apply_r nf1))) + (t_bdHoareS_conseq_bd hs.bhs_cmp (bhs_bd hs)) + (t_on1seq 2 (tac (bhs_pr hs) (bhs_po hs)) (t_apply_r nf1))) tc (* ------------------------------------------------------------------ *) (* hoareF / hoareF / ⊥ / ⊥ *) | FhoareF _, Some ((_, {f_node = FhoareF hs}) as nf1), None, None -> let tac = if notmod then t_hoareF_conseq_nm else t_hoareF_conseq in - t_on1 2 (t_apply_r nf1) (tac hs.hf_pr hs.hf_po tc) + t_on1 2 (t_apply_r nf1) (tac (hf_pr hs) (hf_po hs) tc) (* ------------------------------------------------------------------ *) (* hoareF / hoareF / hoareF / ⊥ *) | FhoareF _, - Some ((_, {f_node = FhoareF hs}) as nf1), + Some ((_, {f_node = FhoareF hf}) as nf1), Some((_, f2) as nf2), None -> let hs2 = pf_as_hoareF !!tc f2 in let tac = if notmod then t_hoareF_conseq_nm else t_hoareF_conseq in - + let pr1, po1 = hf_pr hf, hf_po hf in + let pr2 = ss_inv_rebind (hf_pr hs2) hf.hf_m in + let po2 = ss_inv_rebind (hf_po hs2) hf.hf_m in + (* check that the pre- and post-conditions are well formed *) t_on1seq 2 - (tac (f_and hs.hf_pr hs2.hf_pr) (f_and hs.hf_po hs2.hf_po)) + ((tac (map_ss_inv2 f_and pr1 pr2) + (map_ss_inv2 f_and po1 po2))) (FApi.t_seqsub - (t_hoareF_conseq_conj hs2.hf_pr hs2.hf_po hs.hf_pr hs.hf_po) + (t_hoareF_conseq_conj pr2 po2 pr1 po1) [t_apply_r nf2; t_apply_r nf1]) tc @@ -870,8 +962,8 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = FApi.t_seq t_hoareF_conseq_bdhoare (t_on1seq 1 - (t_bdHoareF_conseq_bd hs.bhf_cmp hs.bhf_bd) - (t_on1seq 2 (tac hs.bhf_pr hs.bhf_po) (t_apply_r nf1))) + (t_bdHoareF_conseq_bd hs.bhf_cmp (bhf_bd hs)) + (t_on1seq 2 (tac (bhf_pr hs) (bhf_po hs)) (t_apply_r nf1))) tc (* ------------------------------------------------------------------ *) (* hoareF / equivF / hoareF *) @@ -879,20 +971,20 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = Some ((_, {f_node = FequivF ef}) as nef), Some((_, f2) as nf2), _ -> let hf2 = pf_as_hoareF !!tc f2 in FApi.t_seqsub - (t_hoareF_conseq_equiv hf2.hf_f ef.ef_pr ef.ef_po hf2.hf_pr hf2.hf_po) + (t_hoareF_conseq_equiv hf2.hf_f (ef_pr ef) (ef_po ef) (hf_pr hf2) (hf_po hf2)) [t_id; t_id; t_apply_r nef; t_apply_r nf2] tc (* ------------------------------------------------------------------ *) (* ehoareS / ehoareS / ⊥ / ⊥ *) | FeHoareS _, Some ((_, {f_node = FeHoareS hs}) as nf1), None, None -> let tac = if notmod then t_ehoareS_conseq_nm else t_ehoareS_conseq in - FApi.t_last (t_apply_r nf1) (tac hs.ehs_pr hs.ehs_po tc) + FApi.t_last (t_apply_r nf1) (tac (ehs_pr hs) (ehs_po hs) tc) (* ------------------------------------------------------------------ *) (* ehoareF / ehoareF / ⊥ / ⊥ *) | FeHoareF _, Some ((_, {f_node = FeHoareF hf}) as nf1), None, None -> let tac = if notmod then t_ehoareF_conseq_nm else t_ehoareF_conseq in - FApi.t_last (t_apply_r nf1) (tac hf.ehf_pr hf.ehf_po tc) + FApi.t_last (t_apply_r nf1) (tac (ehf_pr hf) (ehf_po hf) tc) (* ------------------------------------------------------------------ *) (* ehoareF / equivF / ehoareF *) @@ -900,7 +992,7 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = Some ((_, {f_node = FequivF ef}) as nef), Some((_, f2) as nf2), _ -> let hf2 = pf_as_ehoareF !!tc f2 in FApi.t_seqsub - (t_ehoareF_conseq_equiv hf2.ehf_f ef.ef_pr ef.ef_po hf2.ehf_pr hf2.ehf_po) + (t_ehoareF_conseq_equiv hf2.ehf_f (ef_pr ef) (ef_po ef) (ehf_pr hf2) (ehf_po hf2)) [t_id; t_id; t_apply_r nef; t_apply_r nf2] tc (* ------------------------------------------------------------------ *) @@ -909,8 +1001,8 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_bdHoareS_conseq_nm else t_bdHoareS_conseq in t_on1seq 1 - (t_bdHoareS_conseq_bd hs.bhs_cmp hs.bhs_bd) - (t_on1seq 2 (tac hs.bhs_pr hs.bhs_po) (t_apply_r nf1)) + (t_bdHoareS_conseq_bd hs.bhs_cmp (bhs_bd hs)) + (t_on1seq 2 (tac (bhs_pr hs) (bhs_po hs)) (t_apply_r nf1)) tc (* ------------------------------------------------------------------ *) @@ -925,27 +1017,28 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let m,hi,hh, h0 = as_seq4 (LDecl.fresh_ids (FApi.tc1_hyps tc) ["&m";"_";"_";"_"]) in - let pre = f_and hs.bhs_pr hs2.hs_pr in - let mpre = Fsubst.f_subst_mem mhr m pre in - let post1 = hs0.bhs_po in - let post = hs.bhs_po in - let posta = f_and post hs2.hs_po in + let pre = map_ss_inv2 f_and (bhs_pr hs) (hs_pr hs2) in + (* TODO: dubious *) + let mpre = Fsubst.f_subst_mem pre.m m pre.inv in + let post1 = (bhs_po hs0) in + let post = (bhs_po hs) in + let posta = map_ss_inv2 f_and post (hs_po hs2) in - let concl1 = f_forall_mems [hs0.bhs_m] (f_imp hs0.bhs_pr pre) in + let concl1 = f_forall_mems_ss_inv hs0.bhs_m (map_ss_inv2 f_imp (bhs_pr hs0) pre) in let tc = ( t_cut concl1 @+ [ t_id; (* subgoal 1 : pre *) t_intro_i hi @! - t_cut (f_hoareS_r {hs2 with hs_pr = pre}) @+ [ - t_hoareS_conseq hs2.hs_pr hs2.hs_po @+ + t_cut (f_hoareS (snd hs2.hs_m) pre hs2.hs_s (hs_po hs2)) @+ [ + t_hoareS_conseq (hs_pr hs2) (hs_po hs2) @+ [ EcLowGoal.t_trivial; t_mytrivial; t_clear hi (* subgoal 2 : hs2 *)]; t_intro_i hh @! - (t_bdHoareS_conseq_bd hs.bhs_cmp hs.bhs_bd @+ [ + (t_bdHoareS_conseq_bd hs.bhs_cmp (bhs_bd hs) @+ [ t_id; (* subgoal 3 : bound *) - t_bdHoareS_conseq_conj ~add:false hs2.hs_po post1 @+ [ - t_hoareS_conseq pre hs2.hs_po @+ [ + t_bdHoareS_conseq_conj ~add:false (hs_po hs2) post1 @+ [ + t_hoareS_conseq pre (hs_po hs2) @+ [ t_intros_i [m;h0] @! t_cutdef (ptlocal ~args:[pamemory m; palocal h0] hi) mpre @! EcLowGoal.t_trivial; @@ -954,9 +1047,9 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = tac pre posta @+ [ t_apply_hyp hi; t_id; (* subgoal 4 : post *) - t_bdHoareS_conseq_conj ~add:true hs2.hs_po post @+ [ + t_bdHoareS_conseq_conj ~add:true (hs_po hs2) post @+ [ t_apply_hyp hh; - t_bdHoareS_conseq hs.bhs_pr post @+ [ + t_bdHoareS_conseq (bhs_pr hs) post @+ [ EcLowGoal.t_trivial; t_mytrivial; t_id (* subgoal 5 : bdhoare *) @@ -980,8 +1073,8 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_bdHoareF_conseq_nm else t_bdHoareF_conseq in t_on1seq 1 - (t_bdHoareF_conseq_bd hs.bhf_cmp hs.bhf_bd) - (t_on1seq 2 (tac hs.bhf_pr hs.bhf_po) (t_apply_r nf1)) + (t_bdHoareF_conseq_bd hs.bhf_cmp (bhf_bd hs)) + (t_on1seq 2 (tac (bhf_pr hs) (bhf_po hs)) (t_apply_r nf1)) tc (* ------------------------------------------------------------------ *) @@ -996,27 +1089,29 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_bdHoareF_conseq_nm else t_bdHoareF_conseq in let m,hi,hh, h0 = as_seq4 (LDecl.fresh_ids (FApi.tc1_hyps tc) ["&m";"_";"_";"_"]) in - let pre = f_and hs.bhf_pr hs2.hf_pr in - let mpre = Fsubst.f_subst_mem mhr m pre in - let post1 = hs0.bhf_po in - let post = hs.bhf_po in - let posta = f_and post hs2.hf_po in - let mpr,_ = EcEnv.Fun.hoareF_memenv hs0.bhf_f (FApi.tc1_env tc) in - let concl1 = f_forall_mems [mpr] (f_imp hs0.bhf_pr pre) in + let hs_pr = ss_inv_rebind (bhf_pr hs) hs2.hf_m in + let hs0_pr = ss_inv_rebind (bhf_pr hs0) hs2.hf_m in + let pre = map_ss_inv2 f_and hs_pr (hf_pr hs2) in + let mpre = Fsubst.f_subst_mem pre.m m pre.inv in + let post1 = (bhf_po hs0) in + let post = ss_inv_rebind (bhf_po hs) hs2.hf_m in + let posta = map_ss_inv2 f_and post (hf_po hs2) in + let mpr,_ = EcEnv.Fun.hoareF_memenv hs0.bhf_m hs0.bhf_f (FApi.tc1_env tc) in + let concl1 = f_forall_mems_ss_inv mpr (map_ss_inv2 f_imp hs0_pr pre) in let tc = ( t_cut concl1 @+ [ t_id; (* subgoal 1 : pre *) t_intro_i hi @! - t_cut (f_hoareF_r {hs2 with hf_pr = pre}) @+ [ - t_hoareF_conseq hs2.hf_pr hs2.hf_po @+ + t_cut (f_hoareF pre hs2.hf_f (hf_po hs2)) @+ [ + t_hoareF_conseq (hf_pr hs2) (hf_po hs2) @+ [ EcLowGoal.t_trivial; t_mytrivial; t_clear hi (* subgoal 2 : hs2 *)]; t_intro_i hh @! - (t_bdHoareF_conseq_bd hs.bhf_cmp hs.bhf_bd @+ [ + (t_bdHoareF_conseq_bd hs.bhf_cmp (bhf_bd hs) @+ [ t_id; (* subgoal 3 : bound *) - t_bdHoareF_conseq_conj ~add:false hs2.hf_po post1 @+ [ - t_hoareF_conseq pre hs2.hf_po @+ [ + t_bdHoareF_conseq_conj ~add:false (hf_po hs2) post1 @+ [ + t_hoareF_conseq pre (hf_po hs2) @+ [ t_intros_i [m;h0] @! t_cutdef (ptlocal ~args:[pamemory m; palocal h0] hi) mpre @! EcLowGoal.t_trivial; @@ -1025,9 +1120,9 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = tac pre posta @+ [ t_apply_hyp hi; t_id; (* subgoal 4 : post *) - t_bdHoareF_conseq_conj ~add:true hs2.hf_po post @+ [ + t_bdHoareF_conseq_conj ~add:true (hf_po hs2) post @+ [ t_apply_hyp hh; - t_bdHoareF_conseq hs.bhf_pr post @+ [ + t_bdHoareF_conseq (bhf_pr hs) post @+ [ EcLowGoal.t_trivial; t_mytrivial; t_id (* subgoal 5 : bdhoare *) @@ -1046,19 +1141,20 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = tc (* ------------------------------------------------------------------ *) - (* bdhoareF / equivF / bdhoareF *) + (* bdhoareF / equivF / bdhoareF *) | FbdHoareF _, Some ((_, {f_node = FequivF ef}) as nef), Some((_, f2) as nf2), _ -> let hf2 = pf_as_bdhoareF !!tc f2 in FApi.t_seqsub - (t_bdHoareF_conseq_equiv hf2.bhf_f ef.ef_pr ef.ef_po hf2.bhf_pr hf2.bhf_po) + (t_bdHoareF_conseq_equiv hf2.bhf_f (ef_pr ef) (ef_po ef) + (bhf_pr hf2) (bhf_po hf2)) [t_id; t_id; t_apply_r nef; t_apply_r nf2] tc (* ------------------------------------------------------------------ *) (* equivS / equivS / ⊥ / ⊥ *) | FequivS _, Some ((_, {f_node = FequivS es}) as nf1), None, None -> let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in - t_on1 2 (t_apply_r nf1) (tac es.es_pr es.es_po tc) + t_on1 2 (t_apply_r nf1) (tac (es_pr es) (es_po es) tc) (* ------------------------------------------------------------------ *) (* equivS / equivS / hoareS / hoareS *) @@ -1067,18 +1163,21 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = Some ((_, f2) as nf2), Some ((_, f3) as nf3) -> - let subst1 = Fsubst.f_subst_mem mhr mleft in - let subst2 = Fsubst.f_subst_mem mhr mright in let hs2 = pf_as_hoareS !!tc f2 in let hs3 = pf_as_hoareS !!tc f3 in - let pre = f_ands [es.es_pr; subst1 hs2.hs_pr; subst2 hs3.hs_pr] in - let post = f_ands [es.es_po; subst1 hs2.hs_po; subst2 hs3.hs_po] in + let (ml, mr) = (fst es.es_ml, fst es.es_mr) in + let hs2_pr = ss_inv_generalize_right (ss_inv_rebind (hs_pr hs2) ml) mr in + let hs2_po = ss_inv_generalize_right (ss_inv_rebind (hs_po hs2) ml) mr in + let hs3_pr = ss_inv_generalize_left (ss_inv_rebind (hs_pr hs3) mr) ml in + let hs3_po = ss_inv_generalize_left (ss_inv_rebind (hs_po hs3) mr) ml in + let pre = map_ts_inv f_ands [es_pr es; hs2_pr; hs3_pr] in + let post = map_ts_inv f_ands [es_po es; hs2_po; hs3_po] in let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in t_on1seq 2 (tac pre post) (FApi.t_seqsub (t_equivS_conseq_conj - hs2.hs_pr hs2.hs_po hs3.hs_pr hs3.hs_po es.es_pr es.es_po) + (hs_pr hs2) (hs_po hs2) (hs_pr hs3) (hs_po hs3) (es_pr es) (es_po es)) [t_apply_r nf2; t_apply_r nf3; t_apply_r nf1]) tc @@ -1090,7 +1189,7 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in t_on1seq 2 - (tac es.es_pr es.es_po) + (tac (es_pr es) (es_po es)) (t_hi_conseq notmod None f2 None) tc @@ -1102,28 +1201,31 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in t_on1seq 2 - (tac es.es_pr es.es_po) + (tac (es_pr es) (es_po es)) (t_hi_conseq notmod None None f3) tc (* ------------------------------------------------------------------ *) (* equivS / ? / ? / ⊥ *) | FequivS es, Some _, Some _, None -> - let f3 = f_hoareS (mhr, snd es.es_mr) f_true es.es_sr f_true in + let m = EcIdent.create "&hr" in + let f3 = f_hoareS (snd es.es_mr) {m;inv=f_true} es.es_sr {m;inv=f_true} in t_hi_conseq notmod f1 f2 (Some (None, f3)) tc (* ------------------------------------------------------------------ *) (* equivS / ? / ⊥ / ? *) | FequivS es, Some _, None, Some _ -> - let f2 = f_hoareS (mhr, snd es.es_ml) f_true es.es_sl f_true in + let m = EcIdent.create "&hr" in + let f2 = f_hoareS (snd es.es_ml) {m;inv=f_true} es.es_sl {m;inv=f_true} in t_hi_conseq notmod f1 (Some (None, f2)) f3 tc (* ------------------------------------------------------------------ *) (* equivS / ⊥ / bdhoareS / ⊥ *) - | FequivS _, None, Some ((_, f2) as nf2), None -> - let subst1 = Fsubst.f_subst_mem mhr mleft in + | FequivS es, None, Some ((_, f2) as nf2), None -> let hs = pf_as_bdhoareS !!tc f2 in - let pre, post = subst1 hs.bhs_pr, subst1 hs.bhs_po in + let (ml, mr) = (fst es.es_ml, fst es.es_mr) in + let pre = ss_inv_generalize_right (ss_inv_rebind (bhs_pr hs) ml) mr in + let post = ss_inv_generalize_right (ss_inv_rebind (bhs_po hs) ml) mr in let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in check_is_detbound `Second hs.bhs_bd; @@ -1131,16 +1233,17 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = t_on1seq 2 (tac pre post) (FApi.t_seq - (t_equivS_conseq_bd `Left hs.bhs_pr hs.bhs_po) + (t_equivS_conseq_bd `Left (bhs_pr hs) (bhs_po hs)) (t_apply_r nf2)) tc (* ------------------------------------------------------------------ *) (* equivS / ⊥ / ⊥ / bdhoareS *) - | FequivS _, None, None, Some ((_, f3) as nf3) -> - let subst2 = Fsubst.f_subst_mem mhr mright in + | FequivS es, None, None, Some ((_, f3) as nf3) -> let hs = pf_as_bdhoareS !!tc f3 in - let pre, post = subst2 hs.bhs_pr, subst2 hs.bhs_po in + let (ml, mr) = (fst es.es_ml, fst es.es_mr) in + let pre = ss_inv_generalize_left (ss_inv_rebind (bhs_pr hs) mr) ml in + let post = ss_inv_generalize_left (ss_inv_rebind (bhs_po hs) mr) ml in let tac = if notmod then t_equivS_conseq_nm else t_equivS_conseq in check_is_detbound `Third hs.bhs_bd; @@ -1148,7 +1251,7 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = t_on1seq 2 (tac pre post) (FApi.t_seq - (t_equivS_conseq_bd `Right hs.bhs_pr hs.bhs_po) + (t_equivS_conseq_bd `Right (bhs_pr hs) (bhs_po hs)) (t_apply_r nf3)) tc @@ -1156,7 +1259,7 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = (* equivF / equivF / ⊥ / ⊥ *) | FequivF _, Some ((_, {f_node = FequivF ef}) as nf1), None, None -> let tac = if notmod then t_equivF_conseq_nm else t_equivF_conseq in - t_on1seq 2 (tac ef.ef_pr ef.ef_po) (t_apply_r nf1) tc + t_on1seq 2 (tac (ef_pr ef) (ef_po ef)) (t_apply_r nf1) tc (* ------------------------------------------------------------------ *) (* equivF / equivF / hoareF / hoareF *) @@ -1165,32 +1268,36 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = Some ((_, f2) as nf2), Some ((_, f3) as nf3) -> - let subst1 = Fsubst.f_subst_mem mhr mleft in - let subst2 = Fsubst.f_subst_mem mhr mright in let hs2 = pf_as_hoareF !!tc f2 in let hs3 = pf_as_hoareF !!tc f3 in - let pre = f_ands [ef.ef_pr; subst1 hs2.hf_pr; subst2 hs3.hf_pr] in - let post = f_ands [ef.ef_po; subst1 hs2.hf_po; subst2 hs3.hf_po] in + let (ml, mr) = (ef.ef_ml, ef.ef_mr) in + let hs2_pr = ss_inv_generalize_right (ss_inv_rebind (hf_pr hs2) ml) mr in + let hs3_pr = ss_inv_generalize_left (ss_inv_rebind (hf_pr hs3) mr) ml in + let pre = map_ts_inv f_ands [ef_pr ef; hs2_pr; hs3_pr] in + let hs2_po = ss_inv_generalize_right (ss_inv_rebind (hf_po hs2) ml) mr in + let hs3_po = ss_inv_generalize_left (ss_inv_rebind (hf_po hs3) mr) ml in + let post = map_ts_inv f_ands [ef_po ef; hs2_po; hs3_po] in let tac = if notmod then t_equivF_conseq_nm else t_equivF_conseq in - t_on1seq 2 (tac pre post) (FApi.t_seqsub (t_equivF_conseq_conj - hs2.hf_pr hs2.hf_po hs3.hf_pr hs3.hf_po ef.ef_pr ef.ef_po) + (hf_pr hs2) (hf_po hs2) (hf_pr hs3) (hf_po hs3) (ef_pr ef) (ef_po ef)) [t_apply_r nf2; t_apply_r nf3; t_apply_r nf1]) tc (* ------------------------------------------------------------------ *) (* equivF / ? / ? / ⊥ *) | FequivF ef, Some _, Some _, None -> - let f3 = f_hoareF f_true ef.ef_fr f_true in + let m = EcIdent.create "&hr" in + let f3 = f_hoareF {m;inv=f_true} ef.ef_fr {m;inv=f_true} in t_hi_conseq notmod f1 f2 (Some (None, f3)) tc (* ------------------------------------------------------------------ *) (* equivF / ? / ⊥ / ? *) | FequivF ef, Some _, None, Some _ -> - let f2 = f_hoareF f_true ef.ef_fl f_true in + let m = EcIdent.create "&hr" in + let f2 = f_hoareF {m;inv=f_true} ef.ef_fl {m;inv=f_true} in t_hi_conseq notmod f1 (Some (None, f2)) f3 tc | _ -> @@ -1217,10 +1324,10 @@ let rec t_hi_conseq notmod f1 f2 f3 tc = (* -------------------------------------------------------------------- *) type processed_conseq_info = - | PCI_bd of hoarecmp option * form + | PCI_bd of hoarecmp option * ss_inv -let process_info pe hyps = function - | CQI_bd (cmp, bd) -> PCI_bd (cmp, TTC.pf_process_form pe hyps treal bd) +let process_info pe hyps m = function + | CQI_bd (cmp, bd) -> PCI_bd (cmp, {m; inv=TTC.pf_process_form pe hyps treal bd}) let process_conseq notmod ((info1, info2, info3) : conseq_ppterm option tuple3) tc = let hyps, concl = FApi.tc1_flat tc in @@ -1232,18 +1339,18 @@ let process_conseq notmod ((info1, info2, info3) : conseq_ppterm option tuple3) let penv, qenv, gpre, gpost, ty, fmake = match concl.f_node with | FhoareS hs -> - let env = LDecl.push_active hs.hs_m hyps in + let env = LDecl.push_active_ss hs.hs_m hyps in let fmake pre post c_or_bd = match c_or_bd with | None -> - f_hoareS_r { hs with hs_pr = pre; hs_po = post; } + f_hoareS(snd hs.hs_m) pre hs.hs_s post | Some (PCI_bd (cmp, bd)) -> - f_bdHoareS hs.hs_m pre hs.hs_s post (oget cmp) bd - in (env, env, hs.hs_pr, hs.hs_po, tbool, fmake) + f_bdHoareS (snd hs.hs_m) pre hs.hs_s post (oget cmp) bd + in (env, env, Inv_ss (hs_pr hs), Inv_ss (hs_po hs), tbool, lift_ss_inv2 fmake) | FhoareF hf -> - let penv, qenv = LDecl.hoareF hf.hf_f hyps in + let penv, qenv = LDecl.hoareF hf.hf_m hf.hf_f hyps in let fmake pre post c_or_bd = match c_or_bd with @@ -1252,172 +1359,192 @@ let process_conseq notmod ((info1, info2, info3) : conseq_ppterm option tuple3) | Some (PCI_bd (cmp, bd)) -> f_bdHoareF pre hf.hf_f post (oget cmp) bd - in (penv, qenv, hf.hf_pr, hf.hf_po, tbool, fmake) + in (penv, qenv, Inv_ss (hf_pr hf), Inv_ss (hf_po hf), tbool, lift_ss_inv2 fmake) | FeHoareS hs -> - let env = LDecl.push_active hs.ehs_m hyps in + let env = LDecl.push_active_ss hs.ehs_m hyps in let fmake pre post bd = ensure_none bd; - f_eHoareS_r { hs with ehs_pr = pre; ehs_po = post; } in - (env, env, hs.ehs_pr, hs.ehs_po, txreal, fmake) + f_eHoareS (snd hs.ehs_m) pre hs.ehs_s post in + (env, env, Inv_ss (ehs_pr hs), Inv_ss (ehs_po hs), txreal, lift_ss_inv2 fmake) | FeHoareF hf -> - let penv, qenv = LDecl.hoareF hf.ehf_f hyps in + let penv, qenv = LDecl.hoareF hf.ehf_m hf.ehf_f hyps in let fmake pre post bd = ensure_none bd; - f_eHoareF_r { hf with ehf_pr = pre; ehf_po = post } in - (penv, qenv, hf.ehf_pr, hf.ehf_po, txreal, fmake) + f_eHoareF pre hf.ehf_f post in + (penv, qenv, Inv_ss (ehf_pr hf), Inv_ss (ehf_po hf), txreal, lift_ss_inv2 fmake) | FbdHoareS bhs -> - let env = LDecl.push_active bhs.bhs_m hyps in + let env = LDecl.push_active_ss bhs.bhs_m hyps in let fmake pre post c_or_bd = match c_or_bd with | None -> - f_bdHoareS_r { bhs with bhs_pr = pre; - bhs_po = post; } + f_bdHoareS (snd bhs.bhs_m) pre bhs.bhs_s post bhs.bhs_cmp (bhs_bd bhs) | Some (PCI_bd (cmp,bd)) -> let cmp = odfl bhs.bhs_cmp cmp in - f_bdHoareS_r { bhs with bhs_pr = pre; - bhs_po = post; - bhs_cmp = cmp; - bhs_bd = bd; } - in + f_bdHoareS (snd bhs.bhs_m) pre bhs.bhs_s post cmp bd in - (env, env, bhs.bhs_pr, bhs.bhs_po, tbool, fmake) + (env, env, Inv_ss (bhs_pr bhs), Inv_ss (bhs_po bhs), tbool, lift_ss_inv2 fmake) | FbdHoareF hf -> - let penv, qenv = LDecl.hoareF hf.bhf_f hyps in + let penv, qenv = LDecl.hoareF hf.bhf_m hf.bhf_f hyps in let fmake pre post c_or_bd = match c_or_bd with | None -> - f_bdHoareF pre hf.bhf_f post hf.bhf_cmp hf.bhf_bd + f_bdHoareF pre hf.bhf_f post hf.bhf_cmp (bhf_bd hf) | Some (PCI_bd (cmp,bd)) -> let cmp = odfl hf.bhf_cmp cmp in f_bdHoareF pre hf.bhf_f post cmp bd in - (penv, qenv, hf.bhf_pr, hf.bhf_po, tbool, fmake) + (penv, qenv, Inv_ss (bhf_pr hf), Inv_ss (bhf_po hf), tbool, lift_ss_inv2 fmake) | FequivF ef -> - let penv, qenv = LDecl.equivF ef.ef_fl ef.ef_fr hyps in + let penv, qenv = LDecl.equivF ef.ef_ml ef.ef_mr ef.ef_fl ef.ef_fr hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; f_equivF pre ef.ef_fl ef.ef_fr post - in (penv, qenv, ef.ef_pr, ef.ef_po, tbool, fmake) + in (penv, qenv, Inv_ts (ef_pr ef), Inv_ts (ef_po ef), tbool, lift_ts_inv2 fmake) | FequivS es -> - let env = LDecl.push_all [es.es_ml; es.es_mr] hyps in + let env = LDecl.push_active_ts es.es_ml es.es_mr hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; - f_equivS_r { es with es_pr = pre; es_po = post; } - in (env, env, es.es_pr, es.es_po, tbool, fmake) + f_equivS (snd es.es_ml) (snd es.es_mr) pre es.es_sl es.es_sr post + in (env, env, Inv_ts (es_pr es), Inv_ts (es_po es), tbool, lift_ts_inv2 fmake) | _ -> tc_error !!tc "conseq: not a phl/prhl judgement" in - let pre = pre |> omap (TTC.pf_process_form !!tc penv ty) |> odfl gpre in - let post = post |> omap (TTC.pf_process_form !!tc qenv ty) |> odfl gpost in - let bd = bd |> omap (process_info !!tc penv) in + let pre = pre |> omap (TTC.pf_process_form !!tc penv ty) |> odfl (inv_of_inv gpre) in + let post = post |> omap (TTC.pf_process_form !!tc qenv ty) |> odfl (inv_of_inv gpost) in - fmake pre post bd + let (pre, post, bd) = match gpre, gpost with + | Inv_ss gpre, Inv_ss gpost -> + let bd = bd |> omap (process_info !!tc penv gpre.m) in + (Inv_ss {inv=pre;m=gpre.m}, Inv_ss {inv=post;m=gpost.m}, bd) + | Inv_ts gpre, Inv_ts gpost -> + ensure_none bd; + (Inv_ts {inv=pre;ml=gpre.ml;mr=gpost.mr}, + Inv_ts {inv=post;ml=gpost.ml;mr=gpost.mr}, + None) + | _ -> tc_error !!tc "conseq: pre and post must be of the same kind" in + fmake pre post bd in let process_cut2 side f1 ((pre, post), c_or_bd) = let penv, qenv, gpre, gpost, ty, fmake = match concl.f_node with | FhoareS hs -> - let env = LDecl.push_active hs.hs_m hyps in + let env = LDecl.push_active_ss hs.hs_m hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; - f_hoareS_r { hs with hs_pr = pre; hs_po = post; } - in (env, env, hs.hs_pr, hs.hs_po, tbool, fmake) + f_hoareS (snd hs.hs_m) pre hs.hs_s post + in (env, env, Inv_ss (hs_pr hs), Inv_ss (hs_po hs), tbool, lift_ss_inv2 fmake) | FhoareF hf -> + let m = hf.hf_m in let f, pr, po = match f1 with - | None -> hf.hf_f, hf.hf_pr, hf.hf_po + | None -> hf.hf_f, hf_pr hf, hf_po hf | Some f1 -> match (snd f1).f_node with - | FequivF ef when side = `Left -> ef.ef_fr, f_true, f_true - | _ -> hf.hf_f, hf.hf_pr, hf.hf_po + | FequivF ef when side = `Left -> + ef.ef_fr, {m; inv=f_true}, {m; inv=f_true} + | _ -> hf.hf_f, hf_pr hf, hf_po hf in - let penv, qenv = LDecl.hoareF f hyps in + let penv, qenv = LDecl.hoareF m f hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; f_hoareF pre f post in - (penv, qenv, pr, po, tbool, fmake) + (penv, qenv, Inv_ss pr, Inv_ss po, tbool, lift_ss_inv2 fmake) | FeHoareF hf -> - let f, pr, po = match f1 with - | None -> hf.ehf_f, hf.ehf_pr, hf.ehf_po + let f, pr, po, m = match f1 with + | None -> hf.ehf_f, ehf_pr hf, ehf_po hf, hf.ehf_m | Some f1 -> match (snd f1).f_node with | FequivF ef when side = `Left -> let f_xreal_1 = f_r2xr f_r1 in - ef.ef_fr, f_xreal_1, f_xreal_1 - | _ -> hf.ehf_f, hf.ehf_pr, hf.ehf_po + ef.ef_fr, {m=ef.ef_mr; inv=f_xreal_1}, + {m=ef.ef_mr; inv=f_xreal_1}, ef.ef_mr + | _ -> hf.ehf_f, ehf_pr hf, ehf_po hf, hf.ehf_m in - let penv, qenv = LDecl.hoareF f hyps in + let penv, qenv = LDecl.hoareF m f hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; f_eHoareF pre f post in - (penv, qenv, pr, po, txreal, fmake) + (penv, qenv, Inv_ss pr, Inv_ss po, txreal, lift_ss_inv2 fmake) | FbdHoareS bhs -> - let env = LDecl.push_active bhs.bhs_m hyps in + let env = LDecl.push_active_ss bhs.bhs_m hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; - f_hoareS bhs.bhs_m pre bhs.bhs_s post - in (env, env, bhs.bhs_pr, bhs.bhs_po, tbool, fmake) + f_hoareS (snd bhs.bhs_m) pre bhs.bhs_s post + in (env, env, Inv_ss (bhs_pr bhs), Inv_ss (bhs_po bhs), tbool, lift_ss_inv2 fmake) | FbdHoareF bhf -> - let f, pr, po = match f1 with - | None -> bhf.bhf_f, bhf.bhf_pr, bhf.bhf_po + let f, pr, po, m = match f1 with + | None -> bhf.bhf_f, bhf_pr bhf, bhf_po bhf, bhf.bhf_m | Some f1 -> match (snd f1).f_node with - | FequivF ef when side = `Left -> ef.ef_fr, f_true, f_true - | _ -> bhf.bhf_f, bhf.bhf_pr, bhf.bhf_po + | FequivF ef when side = `Left -> ef.ef_fr, + {m=ef.ef_mr;inv=f_true}, {m=ef.ef_mr;inv=f_true}, ef.ef_mr + | _ -> bhf.bhf_f, bhf_pr bhf, bhf_po bhf, bhf.bhf_m in - let penv, qenv = LDecl.hoareF f hyps in + let penv, qenv = LDecl.hoareF m f hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; f_hoareF pre f post in - (penv, qenv, pr, po, tbool, fmake) + (penv, qenv, Inv_ss pr, Inv_ss po, tbool, lift_ss_inv2 fmake) | FequivF ef -> let f = sideif side ef.ef_fl ef.ef_fr in - let penv, qenv = LDecl.hoareF f hyps in + let m = sideif side ef.ef_ml ef.ef_mr in + let penv, qenv = LDecl.hoareF m f hyps in let fmake pre post c_or_bd = ensure_none c_or_bd; f_hoareF pre f post in - (penv, qenv, f_true, f_true, tbool, fmake) + let f_true = {m; inv=f_true} in + (penv, qenv, Inv_ss f_true, Inv_ss f_true, tbool, lift_ss_inv2 fmake) | FequivS es -> let f = sideif side es.es_sl es.es_sr in let m = sideif side es.es_ml es.es_mr in let m = (mhr, snd m) in - let env = LDecl.push_active m hyps in + let env = LDecl.push_active_ss m hyps in let fmake pre post c_or_bd = match info1, c_or_bd with | None, Some (PCI_bd (cmp,bd)) -> let cmp = odfl FHeq cmp in - f_bdHoareS m pre f post cmp bd + f_bdHoareS (snd m) pre f post cmp bd | None, None -> - let cmp, bd = FHeq, f_r1 in - f_bdHoareS m pre f post cmp bd + let cmp, bd = FHeq, {m=pre.m; inv=f_r1} in + f_bdHoareS (snd m) pre f post cmp bd | _, None -> - f_hoareS m pre f post + f_hoareS (snd m) pre f post | _, Some (PCI_bd (cmp,bd)) -> let cmp = odfl FHeq cmp in - f_bdHoareS m pre f post cmp bd - - in (env, env, f_true, f_true, tbool, fmake) + f_bdHoareS (snd m) pre f post cmp bd in + let f_true = {m=fst m; inv=f_true} in + (env, env, Inv_ss f_true, Inv_ss f_true, tbool, lift_ss_inv2 fmake) | _ -> tc_error !!tc "conseq: not a phl/prhl judgement" in - let pre = pre |> omap (TTC.pf_process_form !!tc penv ty) |> odfl gpre in - let post = post |> omap (TTC.pf_process_form !!tc qenv ty) |> odfl gpost in - let c_or_bd = c_or_bd |> omap (process_info !!tc penv) in + let pre = pre |> omap (TTC.pf_process_form !!tc penv ty) |> odfl (inv_of_inv gpre) in + let post = post |> omap (TTC.pf_process_form !!tc qenv ty) |> odfl (inv_of_inv gpost) in + + let (pre, post, c_or_bd) = match gpre, gpost with + | Inv_ss gpre, Inv_ss gpost -> + let bd = c_or_bd |> omap (process_info !!tc penv gpre.m) in + (Inv_ss {inv=pre;m=gpre.m}, Inv_ss {inv=post;m=gpost.m}, bd) + | Inv_ts gpre, Inv_ts gpost -> + ensure_none c_or_bd; + (Inv_ts {inv=pre;ml=gpre.ml;mr=gpost.mr}, + Inv_ts {inv=post;ml=gpost.ml;mr=gpost.mr}, + None) + | _ -> tc_error !!tc "conseq: pre and post must be of the same kind" in fmake pre post c_or_bd @@ -1471,12 +1598,12 @@ let t_conseqauto ?(delta = true) ?tsolve tc = let todo = match concl.f_node with - | FhoareF hf -> Some (t_hoareF_notmod, cond_hoareF_notmod ~mk_other tc hf.hf_po) - | FhoareS hs -> Some (t_hoareS_notmod, cond_hoareS_notmod ~mk_other tc hs.hs_po ) - | FbdHoareF hf -> Some (t_bdHoareF_notmod, cond_bdHoareF_notmod ~mk_other tc hf.bhf_po) - | FbdHoareS hs -> Some (t_bdHoareS_notmod, cond_bdHoareS_notmod ~mk_other tc hs.bhs_po) - | FequivF ef -> Some (t_equivF_notmod, cond_equivF_notmod ~mk_other tc ef.ef_po) - | FequivS es -> Some (t_equivS_notmod, cond_equivS_notmod ~mk_other tc es.es_po ) + | FhoareF hf -> Some (lift_ss_inv t_hoareF_notmod, cond_hoareF_notmod ~mk_other tc (hf_po hf)) + | FhoareS hs -> Some (lift_ss_inv t_hoareS_notmod, cond_hoareS_notmod ~mk_other tc (hs_po hs) ) + | FbdHoareF hf -> Some (lift_ss_inv t_bdHoareF_notmod, cond_bdHoareF_notmod ~mk_other tc (bhf_po hf)) + | FbdHoareS hs -> Some (lift_ss_inv t_bdHoareS_notmod, cond_bdHoareS_notmod ~mk_other tc (bhs_po hs)) + | FequivF ef -> Some (lift_ts_inv t_equivF_notmod, cond_equivF_notmod ~mk_other tc (ef_po ef)) + | FequivS es -> Some (lift_ts_inv t_equivS_notmod, cond_equivS_notmod ~mk_other tc (es_po es) ) | _ -> None in match todo with @@ -1513,8 +1640,13 @@ let t_conseqauto ?(delta = true) ?tsolve tc = (* Build the inversion substitution *) let s = Fsubst.f_subst_id in let s = List.fold_left2 Fsubst.f_bind_mem s ms bdm in - let s = List.fold_left2 Fsubst.f_bind_local s other (List.map snd bdo) in + let s = List.fold_left2 Fsubst.f_bind_local s other (List.map (fun (bdo: _*ss_inv) -> (snd bdo).inv) bdo) in Fsubst.f_subst s concl in + let post = + match ms with + | [m] -> Inv_ss { inv = post; m} + | [ml; mr] -> Inv_ts { inv = post; ml; mr } + | _ -> failwith "posts should have 1 or 2 memory parameters" in let t_end = FApi.t_try (t_crush ~delta ?tsolve @! t_fail) in FApi.t_first t_end (t_notmod post tc) diff --git a/src/phl/ecPhlConseq.mli b/src/phl/ecPhlConseq.mli index 4400622dc..18c2c22e4 100644 --- a/src/phl/ecPhlConseq.mli +++ b/src/phl/ecPhlConseq.mli @@ -1,43 +1,43 @@ (* -------------------------------------------------------------------- *) open EcUtils open EcParsetree -open EcFol open EcCoreGoal +open EcAst (* -------------------------------------------------------------------- *) (* FIXME: add t_low* to all these tactics *) (* -------------------------------------------------------------------- *) -val t_equivF_conseq : form -> form -> FApi.backward -val t_equivS_conseq : form -> form -> FApi.backward -val t_eagerF_conseq : form -> form -> FApi.backward -val t_hoareF_conseq : form -> form -> FApi.backward -val t_hoareS_conseq : form -> form -> FApi.backward -val t_bdHoareF_conseq : form -> form -> FApi.backward -val t_bdHoareS_conseq : form -> form -> FApi.backward +val t_equivF_conseq : ts_inv -> ts_inv -> FApi.backward +val t_equivS_conseq : ts_inv -> ts_inv -> FApi.backward +val t_eagerF_conseq : ts_inv -> ts_inv -> FApi.backward +val t_hoareF_conseq : ss_inv -> ss_inv -> FApi.backward +val t_hoareS_conseq : ss_inv -> ss_inv -> FApi.backward +val t_bdHoareF_conseq : ss_inv -> ss_inv -> FApi.backward +val t_bdHoareS_conseq : ss_inv -> ss_inv -> FApi.backward -val t_ehoareF_conseq : form -> form -> FApi.backward -val t_ehoareS_conseq : form -> form -> FApi.backward -val t_bdHoareS_conseq_bd : hoarecmp -> form -> FApi.backward -val t_bdHoareF_conseq_bd : hoarecmp -> form -> FApi.backward +val t_ehoareF_conseq : ss_inv -> ss_inv -> FApi.backward +val t_ehoareS_conseq : ss_inv -> ss_inv -> FApi.backward +val t_bdHoareS_conseq_bd : hoarecmp -> ss_inv -> FApi.backward +val t_bdHoareF_conseq_bd : hoarecmp -> ss_inv -> FApi.backward (* -------------------------------------------------------------------- *) -val t_equivF_conseq_nm : form -> form -> FApi.backward -val t_equivS_conseq_nm : form -> form -> FApi.backward -val t_hoareF_conseq_nm : form -> form -> FApi.backward -val t_hoareS_conseq_nm : form -> form -> FApi.backward -val t_bdHoareF_conseq_nm : form -> form -> FApi.backward -val t_bdHoareS_conseq_nm : form -> form -> FApi.backward +val t_equivF_conseq_nm : ts_inv -> ts_inv -> FApi.backward +val t_equivS_conseq_nm : ts_inv -> ts_inv -> FApi.backward +val t_hoareF_conseq_nm : ss_inv -> ss_inv -> FApi.backward +val t_hoareS_conseq_nm : ss_inv -> ss_inv -> FApi.backward +val t_bdHoareF_conseq_nm : ss_inv -> ss_inv -> FApi.backward +val t_bdHoareS_conseq_nm : ss_inv -> ss_inv -> FApi.backward (* -------------------------------------------------------------------- *) -val t_ehoareS_concave : form -> form -> form -> FApi.backward -val t_ehoareF_concave : form -> form -> form -> FApi.backward +val t_ehoareS_concave : ss_inv -> ss_inv -> ss_inv -> FApi.backward +val t_ehoareF_concave : ss_inv -> ss_inv -> ss_inv -> FApi.backward val t_concave_incr : FApi.backward (* -------------------------------------------------------------------- *) -val t_equivS_conseq_bd : side -> EcFol.form -> EcFol.form ->FApi.backward +val t_equivS_conseq_bd : side -> ss_inv -> ss_inv ->FApi.backward (* -------------------------------------------------------------------- *) -val t_conseq : form -> form -> FApi.backward +val t_conseq : inv -> inv -> FApi.backward (* -------------------------------------------------------------------- *) val process_conseq : bool -> conseq_ppterm option tuple3 -> FApi.backward diff --git a/src/phl/ecPhlCoreView.ml b/src/phl/ecPhlCoreView.ml index ef34c91b1..5ae573517 100644 --- a/src/phl/ecPhlCoreView.ml +++ b/src/phl/ecPhlCoreView.ml @@ -3,33 +3,35 @@ open EcFol open EcCoreGoal open EcLowPhlGoal +open EcAst (* -------------------------------------------------------------------- *) let t_hoare_of_bdhoareS_r tc = let bhs = tc1_as_bdhoareS tc in - if not (bhs.bhs_cmp = FHeq && f_equal bhs.bhs_bd f_r0) then + if not (bhs.bhs_cmp = FHeq && f_equal (bhs_bd bhs).inv f_r0) then tc_error !!tc "%s" "bound must be equal to 0%r"; - let concl = f_hoareS bhs.bhs_m bhs.bhs_pr bhs.bhs_s (f_not bhs.bhs_po) in + let concl = f_hoareS (snd bhs.bhs_m) (bhs_pr bhs) bhs.bhs_s (map_ss_inv1 f_not (bhs_po bhs)) in FApi.xmutate1 tc `ViewBdHoare [concl] (* -------------------------------------------------------------------- *) let t_hoare_of_bdhoareF_r tc = let bhf = tc1_as_bdhoareF tc in - if not (bhf.bhf_cmp = FHeq && f_equal bhf.bhf_bd f_r0) then + if not (bhf.bhf_cmp = FHeq && f_equal (bhf_bd bhf).inv f_r0) then tc_error !!tc "%s" "bound must be equal to 0%r"; - let concl = f_hoareF bhf.bhf_pr bhf.bhf_f (f_not bhf.bhf_po) in + let post = map_ss_inv1 f_not (bhf_po bhf) in + let concl = f_hoareF (bhf_pr bhf) bhf.bhf_f post in FApi.xmutate1 tc `ViewBdHoare [concl] (* -------------------------------------------------------------------- *) let t_bdhoare_of_hoareS_r tc = let hs = tc1_as_hoareS tc in - let concl = f_bdHoareS hs.hs_m hs.hs_pr hs.hs_s (f_not hs.hs_po) FHeq f_r0 in + let concl = f_bdHoareS (snd hs.hs_m) (hs_pr hs) hs.hs_s (map_ss_inv1 f_not (hs_po hs)) FHeq {m=fst hs.hs_m;inv=f_r0} in FApi.xmutate1 tc `ViewBdHoare [concl] (* -------------------------------------------------------------------- *) let t_bdhoare_of_hoareF_r tc = let hf = tc1_as_hoareF tc in - let concl = f_bdHoareF hf.hf_pr hf.hf_f (f_not hf.hf_po) FHeq f_r0 in + let concl = f_bdHoareF (hf_pr hf) hf.hf_f (map_ss_inv1 f_not (hf_po hf)) FHeq {m=hf.hf_m;inv=f_r0} in FApi.xmutate1 tc `ViewBdHoare [concl] (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlDeno.ml b/src/phl/ecPhlDeno.ml index ff11151d6..37b79d432 100644 --- a/src/phl/ecPhlDeno.ml +++ b/src/phl/ecPhlDeno.ml @@ -8,6 +8,7 @@ open EcEnv open EcPV open EcPhlPrRw open EcHiGoal +open EcSubst open EcCoreGoal open EcLowGoal @@ -34,40 +35,40 @@ let t_real_le_trans f2 tc = (* -------------------------------------------------------------------- *) let t_core_phoare_deno pre post tc = + let m = pre.m in let env, _, concl = FApi.tc1_eflat tc in let cmp, f, bd, concl_post = match concl.f_node with | Fapp ({f_node = Fop (op, _)}, [f; bd]) when is_pr f && EcPath.p_equal op EcCoreLib.CI_Real.p_real_le -> - (FHle, f, bd, fun ev -> f_imp_simpl ev post) + (FHle, f, bd, fun ev po -> map_ss_inv2 f_imp_simpl ev po) | Fapp ({f_node = Fop (op, _)}, [bd; f]) when is_pr f && EcPath.p_equal op EcCoreLib.CI_Real.p_real_le -> - (FHge, f, bd, fun ev -> f_imp_simpl post ev) + (FHge, f, bd, fun ev po -> map_ss_inv2 f_imp_simpl po ev) | Fapp ({f_node = Fop (op, _)}, [f; bd]) when is_pr f && EcPath.p_equal op EcCoreLib.CI_Bool.p_eq -> - (FHeq, f, bd, f_iff_simpl post) + (FHeq, f, bd, map_ss_inv2 f_iff_simpl) | _ -> tc_error !!tc "invalid goal shape" in let pr = destr_pr f in - let concl_e = f_bdHoareF pre pr.pr_fun post cmp bd in + let concl_e = f_bdHoareF pre pr.pr_fun post cmp {m;inv=bd} in let fun_ = EcEnv.Fun.by_xpath pr.pr_fun env in (* building the substitution for the pre *) - let sargs = PVM.add env pv_arg mhr pr.pr_args PVM.empty in - let smem = Fsubst.f_bind_mem Fsubst.f_subst_id mhr pr.pr_mem in - let concl_pr = Fsubst.f_subst smem (PVM.subst env sargs pre) in + let sargs = PVM.add env pv_arg m pr.pr_args PVM.empty in + let smem = Fsubst.f_bind_mem Fsubst.f_subst_id m pr.pr_mem in + let concl_pr = Fsubst.f_subst smem ((PVM.subst env sargs) pre.inv) in (* building the substitution for the post *) - (* FIXME: - * let smem_ = Fsubst.f_bind_mem Fsubst.f_subst_id mhr mhr in - * let ev = Fsubst.f_subst smem_ ev in *) - let me = EcEnv.Fun.actmem_post mhr fun_ in - let concl_po = f_forall_mems [me] (concl_post pr.pr_event) in + let ev = pr.pr_event in + let me = EcEnv.Fun.actmem_post ev.m fun_ in + let post = ss_inv_rebind post ev.m in + let concl_po = EcSubst.f_forall_mems_ss_inv me (concl_post ev post) in FApi.xmutate1 tc `HlDeno [concl_e; concl_pr; concl_po] @@ -98,19 +99,18 @@ let t_ehoare_deno_r pre post tc = let pr = destr_pr f in let concl_e = f_eHoareF pre pr.pr_fun post in - let mpr, mpo = EcEnv.Fun.hoareF_memenv pr.pr_fun env in + let mpr, mpo = EcEnv.Fun.hoareF_memenv pr.pr_mem pr.pr_fun env in (* pre <= bd *) (* building the substitution for the pre *) let sargs = PVM.add env pv_arg (fst mpr) pr.pr_args PVM.empty in let smem = Fsubst.f_bind_mem Fsubst.f_subst_id (fst mpr) pr.pr_mem in - let pre = Fsubst.f_subst smem (PVM.subst env sargs pre) in + let pre = Fsubst.f_subst smem (PVM.subst env sargs pre.inv) in let concl_pr = f_xreal_le pre (f_r2xr bd) in (* forall m, ev%r%xr <= post *) - let smem = Fsubst.f_bind_mem Fsubst.f_subst_id mhr (fst mpo) in - let ev = Fsubst.f_subst smem pr.pr_event in - let concl_po = f_xreal_le (f_b2xr ev) post in - let concl_po = f_forall_mems [mpo] concl_po in + let ev = pr.pr_event in + let concl_po = map_ss_inv2 f_xreal_le (map_ss_inv1 f_b2xr ev) post in + let concl_po = f_forall_mems_ss_inv mpo concl_po in FApi.xmutate1 tc `HlDeno [concl_e; concl_pr; concl_po] @@ -118,15 +118,17 @@ let t_ehoare_deno_r pre post tc = let cond_pre env prl prr pre = (* building the substitution for the pre *) (* we substitute param by args and left by ml and right by mr *) - let sargs = PVM.add env pv_arg mleft prl.pr_args PVM.empty in - let sargs = PVM.add env pv_arg mright prr.pr_args sargs in + let ml, mr = pre.ml, pre.mr in + let sargs = PVM.add env pv_arg ml prl.pr_args PVM.empty in + let sargs = PVM.add env pv_arg mr prr.pr_args sargs in let smem = Fsubst.f_subst_id in - let smem = Fsubst.f_bind_mem smem mleft prl.pr_mem in - let smem = Fsubst.f_bind_mem smem mright prr.pr_mem in - Fsubst.f_subst smem (PVM.subst env sargs pre) + let smem = Fsubst.f_bind_mem smem ml prl.pr_mem in + let smem = Fsubst.f_bind_mem smem mr prr.pr_mem in + Fsubst.f_subst smem (PVM.subst env sargs pre.inv) let t_equiv_deno_r pre post tc = let env, _, concl = FApi.tc1_eflat tc in + let ml, mr = pre.ml, pre.mr in let cmp, f1, f2 = match concl.f_node with @@ -154,19 +156,17 @@ let t_equiv_deno_r pre post tc = let concl_pr = cond_pre env prl prr pre in (* building the substitution for the post *) - let smeml = Fsubst.f_bind_mem Fsubst.f_subst_id mhr mleft in - let smemr = Fsubst.f_bind_mem Fsubst.f_subst_id mhr mright in - let evl = Fsubst.f_subst smeml prl.pr_event in - let evr = Fsubst.f_subst smemr prr.pr_event in + let evl = ss_inv_generalize_as_left prl.pr_event ml mr in + let evr = ss_inv_generalize_as_right prr.pr_event ml mr in let cmp = match cmp with - | `Eq -> f_iff evl evr - | `Le -> f_imp evl evr - | `Ge -> f_imp evr evl in + | `Eq -> map_ts_inv2 f_iff evl evr + | `Le -> map_ts_inv2 f_imp evl evr + | `Ge -> map_ts_inv2 f_imp evr evl in - let mel = EcEnv.Fun.actmem_post mleft funl in - let mer = EcEnv.Fun.actmem_post mright funr in - let concl_po = f_forall_mems [mel; mer] (f_imp post cmp) in + let mel = EcEnv.Fun.actmem_post ml funl in + let mer = EcEnv.Fun.actmem_post mr funr in + let concl_po = f_forall_mems_ts_inv mel mer (map_ts_inv2 f_imp post cmp) in FApi.xmutate1 tc `HlDeno [concl_e; concl_pr; concl_po] @@ -201,12 +201,14 @@ let process_phoare_deno info tc = | _ -> error () in - let { pr_fun = f; pr_event = event; } = destr_pr f in - let penv, qenv = LDecl.hoareF f hyps in + let { pr_fun = f } as pr = destr_pr f in + let event = pr.pr_event in + let m = event.m in + let penv, qenv = LDecl.hoareF m f hyps in let pre = pre |> omap_dfl (fun p -> TTC.pf_process_formula !!tc penv p) f_true in - let post = post |> omap_dfl (fun p -> TTC.pf_process_formula !!tc qenv p) event in + let post = post |> omap_dfl (fun p -> TTC.pf_process_formula !!tc qenv p) event.inv in - f_bdHoareF pre f post cmp bd + f_bdHoareF {m;inv=pre} f {m;inv=post} cmp {m;inv=bd} in let pt, ax = @@ -215,7 +217,7 @@ let process_phoare_deno info tc = let pre, post = let bhf = pf_as_bdhoareF !!tc ax in - (bhf.bhf_pr, bhf.bhf_po) + (bhf_pr bhf, bhf_po bhf) in FApi.t_first (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) (t_phoare_deno pre post tc) @@ -235,13 +237,15 @@ let process_ehoare_deno info tc = | _ -> error () in - let { pr_fun = f; pr_mem = m; pr_event = event; } = destr_pr f in - let penv, qenv = LDecl.hoareF f hyps in - let smem = Fsubst.f_bind_mem Fsubst.f_subst_id m mhr in - let dpre = f_r2xr (Fsubst.f_subst smem bd) in + let { pr_fun = f } as pr = destr_pr f in + let event = pr.pr_event in + let m = event.m in + let penv, qenv = LDecl.hoareF m f hyps in + let smem = Fsubst.f_bind_mem Fsubst.f_subst_id pr.pr_mem m in + let dpre = {m;inv=f_r2xr (Fsubst.f_subst smem bd)} in - let pre = pre |> omap_dfl (fun p -> TTC.pf_process_xreal !!tc penv p) dpre in - let post = post |> omap_dfl (fun p -> TTC.pf_process_xreal !!tc qenv p) (f_b2xr event) in + let pre = pre |> omap_dfl (fun p -> {m;inv=TTC.pf_process_xreal !!tc penv p}) dpre in + let post = post |> omap_dfl (fun p -> {m;inv=TTC.pf_process_xreal !!tc qenv p}) (map_ss_inv1 f_b2xr event) in f_eHoareF pre f post in @@ -252,7 +256,7 @@ let process_ehoare_deno info tc = let pre, post = let hf = pf_as_ehoareF !!tc ax in - (hf.ehf_pr, hf.ehf_po) + (ehf_pr hf, ehf_po hf) in FApi.t_first (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) (t_ehoare_deno pre post tc) @@ -282,7 +286,7 @@ let t_pr_pos tc = let _, fpr = DestrReal.le (tc1_goal tc) in destr_pr fpr with DestrError _ -> tc_error !!tc "invalid goal shape" in - let prf = f_pr_r {pr with pr_event = f_false} in + let prf = f_pr_r {pr with pr_event = {m=pr.pr_event.m; inv=f_false}} in (t_real_le_trans prf @+ [ t_pr_rewrite ("mu_false", None) @! t_true; t_pr_rewrite ("mu_sub", None) @! t_true]) tc @@ -292,18 +296,16 @@ let t_equiv_deno_bad pre tc = let env, _hyps, concl = FApi.tc1_eflat tc in let fpr1, fpr2, fprb = tc_destr_deno_bad tc env concl in let pr1 = destr_pr fpr1 and pr2 = destr_pr fpr2 and prb = destr_pr fprb in - let fand = f_and pr2.pr_event (f_not prb.pr_event) in - let pro = f_pr_r { pr2 with pr_event = f_or fand prb.pr_event } in - let pra = f_pr_r { pr2 with pr_event = fand } in + let fand = map_ss_inv2 f_and pr2.pr_event (map_ss_inv1 f_not prb.pr_event) in + let pro = f_pr pr2.pr_mem pr2.pr_fun pr2.pr_args (map_ss_inv2 f_or fand prb.pr_event) in + let pra = f_pr pr2.pr_mem pr2.pr_fun pr2.pr_args fand in let t_false tc = t_apply_prept (`UG real_upto_false) tc in - + let ml, mr = pre.ml, pre.mr in let post = - let subst_l = Fsubst.f_subst_mem mhr mleft in - let subst_r = Fsubst.f_subst_mem mhr mright in - let ev1 = subst_l pr1.pr_event in - let ev2 = subst_r pr2.pr_event in - let bad2 = subst_r prb.pr_event in - f_imp (f_not bad2) (f_imp ev1 ev2) in + let ev1 = ss_inv_generalize_as_left pr1.pr_event ml mr in + let ev2 = ss_inv_generalize_as_right pr2.pr_event ml mr in + let bad2 = ss_inv_generalize_as_right prb.pr_event ml mr in + map_ts_inv2 f_imp (map_ts_inv1 f_not bad2) (map_ts_inv2 f_imp ev1 ev2) in (t_real_le_trans pro @+ [t_equiv_deno pre post @+ [ @@ -342,6 +344,7 @@ let tc_destr_deno_bad2 tc env f = (* -------------------------------------------------------------------- *) let t_equiv_deno_bad2 pre bad1 tc = + let ml, mr = pre.ml, pre.mr in let env, hyps, concl = FApi.tc1_eflat tc in let fpr1, fpr2, fprb = tc_destr_deno_bad2 tc env concl in let pr1 = destr_pr fpr1 and pr2 = destr_pr fpr2 and @@ -350,17 +353,18 @@ let t_equiv_deno_bad2 pre bad1 tc = let ev1 = pr1.pr_event and ev2 = pr2.pr_event in let bad2 = prb.pr_event in let post = - let subst_l = Fsubst.f_subst_mem mhr mleft in - let subst_r = Fsubst.f_subst_mem mhr mright in - let bad2 = subst_r bad2 in - f_and (f_iff (subst_l bad1) bad2) - (f_imp (f_not bad2) (f_iff (subst_l ev1) (subst_r ev2))) in + let bad1 = ss_inv_generalize_as_left bad1 ml mr in + let ev1 = ss_inv_generalize_as_left ev1 ml mr in + let bad2 = ss_inv_generalize_as_right bad2 ml mr in + let ev2 = ss_inv_generalize_as_right ev2 ml mr in + map_ts_inv2 f_and (map_ts_inv2 f_iff bad1 bad2) + (map_ts_inv2 f_imp (map_ts_inv1 f_not bad2) (map_ts_inv2 f_iff ev1 ev2)) in let equiv = f_equivF pre f1 f2 post in let cpre = cond_pre env pr1 pr2 pre in - let fpreb1 = f_pr_r {pr1 with pr_event = f_and ev1 bad1} in - let fpren1 = f_pr_r {pr1 with pr_event = f_and ev1 (f_not bad1) } in - let fpreb2 = f_pr_r {pr2 with pr_event = f_and ev2 bad2} in - let fpren2 = f_pr_r {pr2 with pr_event = f_and ev2 (f_not bad2) } in + let fpreb1 = f_pr pr1.pr_mem pr1.pr_fun pr1.pr_args (map_ss_inv2 f_and ev1 bad1) in + let fpren1 = f_pr pr1.pr_mem pr1.pr_fun pr1.pr_args (map_ss_inv2 f_and ev1 (map_ss_inv1 f_not bad1)) in + let fpreb2 = f_pr pr1.pr_mem pr2.pr_fun pr2.pr_args (map_ss_inv2 f_and ev2 bad2) in + let fpren2 = f_pr pr1.pr_mem pr2.pr_fun pr2.pr_args (map_ss_inv2 f_and ev2 (map_ss_inv1 f_not bad2)) in let fabs' = f_real_abs (f_real_sub (f_real_add fpreb1 fpren1) (f_real_add fpreb2 fpren2)) in @@ -400,39 +404,43 @@ let t_equiv_deno_bad2 pre bad1 tc = (* -------------------------------------------------------------------- *) let process_pre tc hyps prl prr pre post = let fl = prl.pr_fun and fr = prr.pr_fun in + let ml, mr = post.ml, post.mr in match pre with | Some p -> - let penv, _ = LDecl.equivF fl fr hyps in - TTC.pf_process_formula !!tc penv p + let penv, _ = LDecl.equivF ml mr fl fr hyps in + {ml;mr;inv=TTC.pf_process_formula !!tc penv p} | None -> let al = prl.pr_args and ar = prr.pr_args in - let ml = prl.pr_mem and mr = prr.pr_mem in + let pml = prl.pr_mem and pmr = prr.pr_mem in + let env = LDecl.toenv hyps in let eqs = ref [] in let push f = eqs := f :: !eqs in - let dopv m mi x ty = - if is_glob x then push (f_eq (f_pvar x ty m) (f_pvar x ty mi)) in + let dopv m mi gen_o x ty = + if is_glob x then push (gen_o (map_ss_inv1 (fun f -> f_eq f (f_pvar x ty mi).inv) (f_pvar x ty m))) in - let doglob m mi g = push (f_eq (NormMp.norm_glob env m g) (NormMp.norm_glob env mi g)) in - let dof f a m mi = + let doglob m mi gen_o g = push (gen_o ((map_ss_inv1 (fun f -> f_eq f (NormMp.norm_glob env mi g).inv)) (NormMp.norm_glob env m g))) in + let dof f a m mi gen_o = try - let fv = PV.remove env pv_res (PV.fv env m post) in - PV.iter (dopv m mi) (doglob m mi) (eqobs_inF_refl env f fv); + let fv = PV.remove env pv_res (PV.fv env m post.inv) in + PV.iter (dopv m mi gen_o) (doglob m mi gen_o) (eqobs_inF_refl env f fv); if not (EcReduction.EqTest.for_type env a.f_ty tunit) then - push (f_eq (f_pvarg a.f_ty m) a) + push (map_ts_inv1 (fun f -> f_eq f a) (gen_o (f_pvarg a.f_ty m))) with EcCoreGoal.TcError _ | EqObsInError -> () in - dof fl al mleft ml; dof fr ar mright mr; - f_ands !eqs + let gen_r f = ss_inv_generalize_right f mr in + let gen_l f = ss_inv_generalize_left f ml in + dof fl al ml pml gen_r; dof fr ar mr pmr gen_l; + map_ts_inv f_ands !eqs (* -------------------------------------------------------------------- *) -let post_iff eq env evl evr = - let post = f_iff evl evr in +let post_iff ml mr eq env evl evr = + let post = map_ts_inv2 f_iff evl evr in try if not eq then raise Not_found; - Mpv2.to_form mleft mright - (Mpv2.needed_eq env mleft mright post) f_true + {ml;mr;inv=Mpv2.to_form + (Mpv2.needed_eq env post) ml mr f_true} with Not_found -> post (* -------------------------------------------------------------------- *) @@ -448,22 +456,24 @@ let process_equiv_deno1 info eq tc = | _ -> tc_error !!tc "invalid goal shape" in - let { pr_fun = fl; pr_event = evl } as prl = destr_pr f1 in - let { pr_fun = fr; pr_event = evr } as prr = destr_pr f2 in + let ml , mr = EcIdent.create "&1", EcIdent.create "&2" in + + let { pr_fun = fl } as prl = destr_pr f1 in + let evl = ss_inv_generalize_as_left prl.pr_event ml mr in + let { pr_fun = fr } as prr = destr_pr f2 in + let evr = ss_inv_generalize_as_right prr.pr_event ml mr in let post = match post with | Some p -> - let _, qenv = LDecl.equivF fl fr hyps in - TTC.pf_process_formula !!tc qenv p + let _, qenv = LDecl.equivF ml mr fl fr hyps in + {ml;mr;inv=TTC.pf_process_formula !!tc qenv p} | None -> - let evl = Fsubst.f_subst_mem mhr mleft evl in - let evr = Fsubst.f_subst_mem mhr mright evr in match op with | _ when EcPath.p_equal op EcCoreLib.CI_Bool.p_eq -> - post_iff eq env evl evr + (post_iff ml mr eq env evl evr) | _ when EcPath.p_equal op EcCoreLib.CI_Real.p_real_le -> - f_imp evl evr + map_ts_inv2 f_imp evl evr | _ -> tc_error !!tc "not able to reconize a comparison operator" in @@ -478,7 +488,7 @@ let process_equiv_deno1 info eq tc = let pre, post = let ef = pf_as_equivF !!tc ax in - (ef.ef_pr, ef.ef_po) + (ef_pr ef, ef_po ef) in FApi.t_first (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) (t_equiv_deno pre post tc) @@ -489,20 +499,22 @@ let process_equiv_deno_bad info tc = let env, hyps, concl = FApi.tc1_eflat tc in let fpr1, fpr2, fprb = tc_destr_deno_bad tc env concl in - let { pr_fun = fl; pr_event = evl } as prl = destr_pr fpr1 in - let { pr_fun = fr; pr_event = evr } as prr = destr_pr fpr2 in + let { pr_fun = fl ; pr_event = evl } as prl = destr_pr fpr1 in + let { pr_fun = fr ; pr_event = evr } as prr = destr_pr fpr2 in + + let ml , mr = EcIdent.create "&1", EcIdent.create "&2" in let post = match post with | Some p -> - let _, qenv = LDecl.equivF fl fr hyps in - TTC.pf_process_formula !!tc qenv p + let _, qenv = LDecl.equivF ml mr fl fr hyps in + {ml;mr;inv=TTC.pf_process_formula !!tc qenv p} | None -> - let evl = Fsubst.f_subst_mem mhr mleft evl in - let evr = Fsubst.f_subst_mem mhr mright evr in - let bad = (destr_pr fprb).pr_event in - let bad = Fsubst.f_subst_mem mhr mright bad in - f_imps [f_not bad;evl] evr in + let evl = ss_inv_generalize_as_left evl ml mr in + let evr = ss_inv_generalize_as_right evr ml mr in + let bad = ss_inv_generalize_as_right (destr_pr fprb).pr_event ml mr in + let f_imps' l = f_imps (List.tl l) (List.hd l) in + map_ts_inv f_imps' [evr; map_ts_inv1 f_not bad; evl] in let pre = process_pre tc hyps prl prr pre post in f_equivF pre fl fr post @@ -513,12 +525,12 @@ let process_equiv_deno_bad info tc = ~prcut:process_cut tc info in let equiv = pf_as_equivF !!tc ax in - let pre = equiv.ef_pr in + let pre = (ef_pr equiv) in let torotate = ref 1 in let t_sub = FApi.t_or (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) - (EcPhlConseq.t_equivF_conseq pre equiv.ef_po @+ + (EcPhlConseq.t_equivF_conseq pre (ef_po equiv) @+ [t_true; (fun tc -> incr torotate;t_id tc); EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt]) in let gs = @@ -538,28 +550,29 @@ let process_equiv_deno_bad2 info eq bad1 tc = let env, hyps, concl = FApi.tc1_eflat tc in let fpr1, fpr2, fprb = tc_destr_deno_bad2 tc env concl in - let { pr_fun = fl; pr_event = evl } as prl = destr_pr fpr1 in + let { pr_fun = fl; pr_mem = ml ; pr_event = evl } as prl = destr_pr fpr1 in let { pr_fun = fr; pr_event = evr } as prr = destr_pr fpr2 in + let ml' , mr' = EcIdent.create "&1", EcIdent.create "&2" in + let bad1 = - let _, qenv = LDecl.hoareF fl hyps in - TTC.pf_process_formula !!tc qenv bad1 in + let _, qenv = LDecl.hoareF ml fl hyps in + {m=ml;inv=TTC.pf_process_formula !!tc qenv bad1} in let process_cut (pre, post) = let post = match post with | Some p -> - let _, qenv = LDecl.equivF fl fr hyps in - TTC.pf_process_formula !!tc qenv p + let _, qenv = LDecl.equivF ml' mr' fl fr hyps in + {ml=ml';mr=mr';inv=TTC.pf_process_formula !!tc qenv p} | None -> - let evl = Fsubst.f_subst_mem mhr mleft evl in - let evr = Fsubst.f_subst_mem mhr mright evr in - let bad1 = Fsubst.f_subst_mem mhr mleft bad1 in - let bad2 = (destr_pr fprb).pr_event in - let bad2 = Fsubst.f_subst_mem mhr mright bad2 in - let iff = post_iff eq env evl evr in - f_and (f_iff bad1 bad2) (f_imp (f_not bad2) iff) in + let evl = ss_inv_generalize_as_left evl ml' mr' in + let evr = ss_inv_generalize_as_right evr ml' mr' in + let bad1 = ss_inv_generalize_as_left bad1 ml' mr' in + let bad2 = ss_inv_generalize_as_right (destr_pr fprb).pr_event ml' mr' in + let iff = post_iff ml' mr' eq env evl evr in + map_ts_inv2 f_and (map_ts_inv2 f_iff bad1 bad2) (map_ts_inv2 f_imp (map_ts_inv1 f_not bad2) iff) in let pre = process_pre tc hyps prl prr pre post in @@ -571,12 +584,12 @@ let process_equiv_deno_bad2 info eq bad1 tc = ~prcut:process_cut tc info in let equiv = pf_as_equivF !!tc ax in - let pre = equiv.ef_pr in + let pre = (ef_pr equiv) in let torotate = ref 1 in let t_sub = FApi.t_or (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) - (EcPhlConseq.t_equivF_conseq pre equiv.ef_po @+ + (EcPhlConseq.t_equivF_conseq pre (ef_po equiv) @+ [t_true; (fun tc -> incr torotate;t_id tc); EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt]) in let gs = diff --git a/src/phl/ecPhlDeno.mli b/src/phl/ecPhlDeno.mli index e61f66e3a..4d5551321 100644 --- a/src/phl/ecPhlDeno.mli +++ b/src/phl/ecPhlDeno.mli @@ -1,11 +1,11 @@ (* -------------------------------------------------------------------- *) open EcParsetree -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) -val t_phoare_deno : form -> form -> backward -val t_equiv_deno : form -> form -> backward +val t_phoare_deno : ss_inv -> ss_inv -> backward +val t_equiv_deno : ts_inv -> ts_inv -> backward (* -------------------------------------------------------------------- *) type denoff = deno_ppterm * bool * pformula option diff --git a/src/phl/ecPhlEager.ml b/src/phl/ecPhlEager.ml index 65d1541a6..02fc7f1f3 100644 --- a/src/phl/ecPhlEager.ml +++ b/src/phl/ecPhlEager.ml @@ -20,10 +20,10 @@ module TTC = EcProofTyping let pf_destr_eqobsS pf env f = let es = destr_equivS f in let of_form = - try Mpv2.of_form env (fst es.es_ml) (fst es.es_mr) + try Mpv2.of_form env with Not_found -> tc_error pf "cannot reconize a set of equalities" in - (es, es.es_sl, es.es_sr, of_form es.es_pr, of_form es.es_po) + (es, es.es_sl, es.es_sr, of_form (es_pr es), of_form (es_po es)) (* -------------------------------------------------------------------- *) let pf_hSS pf hyps h = @@ -60,12 +60,14 @@ let tc1_destr_eagerS tc s s' = (* This ensure condition (d) and (e) of the eager_seq rule. *) let pf_compat pf env modS modS' eqR eqIs eqXs = if not (Mpv2.subset eqIs eqR) then begin - let eqR = Mpv2.to_form mleft mright eqR f_true in - let eqIs = Mpv2.to_form mleft mright eqIs f_true in + let ml, mr = mleft, mright in + let f_true = {ml; mr; inv=f_true} in + let eqR = Mpv2.to_form_ts_inv eqR f_true in + let eqIs = Mpv2.to_form_ts_inv eqIs f_true in tc_error_lazy pf (fun fmt -> let ppe = EcPrinting.PPEnv.ofenv env in Format.fprintf fmt "%a should be include in %a" - (EcPrinting.pp_form ppe) eqIs (EcPrinting.pp_form ppe) eqR) + (EcPrinting.pp_form ppe) eqIs.inv (EcPrinting.pp_form ppe) eqR.inv) end; let check_pv x1 x2 _ = @@ -98,7 +100,7 @@ let t_eager_seq_r i j eqR h tc = (* h is a proof of (h) *) let tH, (_, s, s', eqIs, eqXs) = pf_hSS !!tc hyps h in let eC, c, c' = tc1_destr_eagerS tc s s' in - let seqR = Mpv2.of_form env (fst eC.es_ml) (fst eC.es_mr) eqR in + let seqR = Mpv2.of_form env eqR in (* check (d) and (e) *) pf_compat !!tc env (s_write env s) (s_write env s') seqR eqIs eqXs; @@ -107,27 +109,12 @@ let t_eager_seq_r i j eqR h tc = let c1 ,c2 = s_split env i c in let c1',c2' = s_split env j c' in - let to_form eq = Mpv2.to_form (fst eC.es_ml) (fst eC.es_mr) eq f_true in - - let a = f_equivS_r { eC with - es_sl = stmt (s.s_node@c1); - es_sr = stmt (c1'@s'.s_node); - es_po = eqR; - } - and b = f_equivS_r { eC with - es_pr = eqR; - es_sl = stmt (s.s_node@c2); - es_sr = stmt (c2'@s'.s_node); - } - and c = f_equivS_r { eC with - es_ml = (fst eC.es_ml, snd eC.es_mr); - es_pr = to_form (Mpv2.eq_fv2 seqR); - es_sl = stmt c2'; - es_sr = stmt c2'; - es_po = to_form eqO2; - } + let to_form eq = Mpv2.to_form_ts_inv eq {ml=(fst eC.es_ml); mr=(fst eC.es_mr); inv=f_true} in - in + let a = f_equivS (snd eC.es_ml) (snd eC.es_mr) (es_pr eC) (stmt (s.s_node@c1)) (stmt (c1'@s'.s_node)) eqR + and b = f_equivS (snd eC.es_ml) (snd eC.es_mr) eqR (stmt (s.s_node@c2)) (stmt (c2'@s'.s_node)) (es_po eC) + and c = f_equivS (snd eC.es_mr) (snd eC.es_mr) (to_form (Mpv2.eq_fv2 seqR)) + (stmt c2') (stmt c2') (to_form eqO2) in FApi.t_first (t_apply_hyp h) @@ -135,46 +122,40 @@ let t_eager_seq_r i j eqR h tc = (* -------------------------------------------------------------------- *) let t_eager_if_r tc = - let hyps = FApi.tc1_hyps tc in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in let (e , c1 , c2 ), s = pf_last_if !!tc es.es_sl in let (e', c1', c2'), s' = pf_first_if !!tc es.es_sr in - let fel = form_of_expr (fst es.es_ml) e in - let fer = form_of_expr (fst es.es_mr) e' in - let fe = form_of_expr mhr e in - - let m2 = as_seq1 (LDecl.fresh_ids hyps ["&m2"]) in + let fel = ss_inv_generalize_right (ss_inv_of_expr ml e) mr in + let fer = ss_inv_generalize_left (ss_inv_of_expr mr e') ml in let aT = - f_forall - [(mleft, GTmem (snd es.es_ml)); (mright, GTmem (snd es.es_mr))] - (f_imp es.es_pr (f_eq fel fer)) in + EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr + (map_ts_inv2 f_imp (es_pr es) (map_ts_inv2 f_eq fel fer)) in let bT = let b = EcIdent.create "b1" in - let eqb = f_eq fe (f_local b tbool) in - let sub = Fsubst.f_subst_id in - let sub = Fsubst.f_bind_mem sub mleft mhr in - let sub = Fsubst.f_bind_mem sub mright m2 in - let p = Fsubst.f_subst sub es.es_pr in + let fe = ss_inv_generalize_right (ss_inv_of_expr ml e) mr in + let eqb = map_ts_inv2 f_eq fe {ml;mr;inv=f_local b tbool} in - f_forall - [(m2, GTmem (snd es.es_mr)); (b, GTty tbool)] - (f_hoareS (mhr, snd es.es_ml) (f_and p eqb) s eqb) in + EcSubst.f_forall_mems_ss_inv es.es_mr + (map_ss_inv1 + (f_forall [(b, GTty tbool)]) + (ts_inv_lower_left2 (fun pr po -> f_hoareS (snd es.es_ml) pr s po) (map_ts_inv2 f_and (es_pr es) eqb) eqb)) in let cT = - let pre = f_and es.es_pr (f_eq fel f_true) in + let pre = map_ts_inv2 f_and (es_pr es) (map_ts_inv2 f_eq fel {ml;mr;inv=f_true}) in let st = stmt (s.s_node @ c1.s_node) in let st' = stmt (c1'.s_node @ s'.s_node) in - f_equivS es.es_ml es.es_mr pre st st' es.es_po in + f_equivS (snd es.es_ml) (snd es.es_mr) pre st st' (es_po es) in let dT = - let pre = f_and es.es_pr (f_eq fel f_false) in + let pre = map_ts_inv2 f_and (es_pr es) (map_ts_inv2 f_eq fel {ml;mr;inv=f_false}) in let st = stmt (s.s_node @ c2.s_node) in let st' = stmt (c2'.s_node @ s'.s_node) in - f_equivS es.es_ml es.es_mr pre st st' es.es_po in + f_equivS (snd es.es_ml) (snd es.es_mr) pre st st' (es_po es) in FApi.xmutate1 tc `EagerIf [aT; bT; cT; dT] @@ -184,52 +165,39 @@ let t_eager_while_r h tc = let tH, (_, s, s', eqIs, eqXs) = pf_hSS !!tc hyps h in let eC, wc, wc' = tc1_destr_eagerS tc s s' in + let ml, mr = fst eC.es_ml, fst eC.es_mr in let (e , c ), n = pf_first_while !!tc wc in let (e', c'), n' = pf_first_while !!tc wc' in - if not (List.is_empty n.s_node && List.is_empty n'.s_node) then tc_error !!tc "no statements should followed the while loops"; - let to_form eq = Mpv2.to_form (fst eC.es_ml) (fst eC.es_mr) eq f_true in + let to_form eq = Mpv2.to_form_ts_inv eq {ml=(fst eC.es_ml);mr=(fst eC.es_mr);inv=f_true} in - let eqI = eC.es_pr in + let eqI = (es_pr eC) in let seqI = try - Mpv2.of_form env (fst eC.es_ml) (fst eC.es_mr) eqI + Mpv2.of_form env eqI with Not_found -> tc_error_lazy !!tc (fun fmt -> let ppe = EcPrinting.PPEnv.ofenv env in - Format.fprintf fmt "recognize equalities in %a@." (EcPrinting.pp_form ppe) eqI) + Format.fprintf fmt "recognize equalities in %a@." (EcPrinting.pp_form ppe) eqI.inv) in let eqI2 = to_form (Mpv2.eq_fv2 seqI) in - let e1 = form_of_expr (fst eC.es_ml) e in - let e2 = form_of_expr (fst eC.es_mr) e' in - let post = Mpv2.to_form (fst eC.es_ml) (fst eC.es_mr) (Mpv2.union seqI eqXs) (f_not e1) in + let e1 = ss_inv_generalize_right (ss_inv_of_expr ml e) mr in + let e2 = ss_inv_generalize_left (ss_inv_of_expr mr e') ml in + let post = Mpv2.to_form_ts_inv (Mpv2.union seqI eqXs) (map_ts_inv1 f_not e1) in (* check (e) and (f) *) pf_compat !!tc env (s_write env s) (s_write env s') seqI eqIs eqXs; - let aT = - f_forall - [mleft,GTmem (snd eC.es_ml); mright, GTmem (snd eC.es_mr)] - (f_imp eqI (f_eq e1 e2)) - - and bT = f_equivS_r { eC with - es_pr = f_and_simpl eqI e1; - es_sl = stmt (s.s_node@c.s_node); - es_sr = stmt (c'.s_node@s'.s_node); - es_po = eqI; - } - - and cT = f_equivS_r { eC with - es_ml = (fst eC.es_ml, snd eC.es_mr); - es_pr = eqI2; - es_sl = c'; - es_sr = c'; - es_po = eqI2; - } + let aT = EcSubst.f_forall_mems_ts_inv eC.es_ml eC.es_mr + (map_ts_inv2 f_imp eqI (map_ts_inv2 f_eq e1 e2)) + and bT = f_equivS (snd eC.es_ml) (snd eC.es_mr) (map_ts_inv2 f_and_simpl eqI e1) (stmt (s.s_node@c.s_node)) + (stmt (c'.s_node@s'.s_node)) eqI + + and cT = f_equivS (snd eC.es_mr) (snd eC.es_mr) eqI2 c' c' eqI2 in let tsolve tc = @@ -247,6 +215,7 @@ let t_eager_while_r h tc = let t_eager_fun_def_r tc = let env = FApi.tc1_env tc in let eg = tc1_as_eagerF tc in + let ml, mr = eg.eg_ml, eg.eg_mr in let fl, fr = (NormMp.norm_xfun env eg.eg_fl, @@ -257,11 +226,11 @@ let t_eager_fun_def_r tc = EcPhlFun.check_concrete !!tc env fr; let (memenvl, (fsigl,fdefl), - memenvr, (fsigr,fdefr), env) = Fun.equivS fl fr env in + memenvr, (fsigr,fdefr), env) = Fun.equivS ml mr fl fr env in let extend mem fdef = match fdef.f_ret with - | None -> f_tt, mem, fdef.f_body + | None -> {m=fst mem;inv=f_tt}, mem, fdef.f_body | Some e -> let v = { ov_name = Some "result"; ov_type = e.e_ty } in let mem, s = EcMemory.bind_fresh v mem in @@ -275,22 +244,15 @@ let t_eager_fun_def_r tc = let er, memr, sfr = extend memenvr fdefr in let ml, mr = EcMemory.memory meml, EcMemory.memory memr in let s = PVM.empty in - let s = PVM.add env pv_res ml el s in - let s = PVM.add env pv_res mr er s in - let post = PVM.subst env s eg.eg_po in + let s = PVM.add env pv_res ml el.inv s in + let s = PVM.add env pv_res mr er.inv s in + let post = map_ts_inv1 (PVM.subst env s) (eg_po eg) in let s = PVM.empty in let s = EcPhlFun.subst_pre env fsigl ml s in let s = EcPhlFun.subst_pre env fsigr mr s in - let pre = PVM.subst env s eg.eg_pr in + let pre = map_ts_inv1 (PVM.subst env s) (eg_pr eg) in - let cond = f_equivS_r { - es_ml = meml; - es_mr = memr; - es_sl = s_seq eg.eg_sl sfl; - es_sr = s_seq sfr eg.eg_sr; - es_pr = pre; - es_po = post; - } in + let cond = f_equivS (snd meml) (snd memr) pre (s_seq eg.eg_sl sfl) (s_seq sfr eg.eg_sr) post in FApi.xmutate1 tc `EagerFunDef [cond] @@ -311,17 +273,17 @@ let t_eager_fun_abs_r eqI h tc = let do1 og sg = let ef = destr_equivF og in let torefl f = - Mpv2.to_form mleft mright + Mpv2.to_form_ts_inv (Mpv2.eq_refl (PV.fv env mright f)) - f_true + {ml=mleft;mr=mright;inv=f_true} in - f_eagerF ef.ef_pr s ef.ef_fl ef.ef_fr s' ef.ef_po + f_eagerF (ef_pr ef) s ef.ef_fl ef.ef_fr s' (ef_po ef) :: f_equivF (torefl ef.ef_pr) ef.ef_fr ef.ef_fr (torefl ef.ef_po) :: sg in let sg = List.fold_right do1 sg [] in - let seqI = Mpv2.of_form env mleft mright eqI in + let seqI = Mpv2.of_form env eqI in (* check (e) and (f)*) pf_compat !!tc env (s_write env s) (s_write env s') seqI eqIs eqXs; @@ -358,15 +320,13 @@ let t_eager_call_r fpre fpost tc = List.iter check_a argsl; - let ml = EcMemory.memory es.es_ml in - let mr = EcMemory.memory es.es_mr in let modil = PV.union (f_write env fl) swl in let modir = PV.union (f_write env fr) swr in let post = EcPhlCall.wp2_call env fpre fpost (lvl, fl, argsl) modil - (lvr,fr,argsr) modir ml mr es.es_po hyps in + (lvr,fr,argsr) modir (es_po es) hyps in let f_concl = f_eagerF fpre sl fl fr sr fpost in - let concl = f_equivS_r { es with es_sl = stmt []; es_sr = stmt []; es_po = post; } in + let concl = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) (stmt []) (stmt []) post in FApi.xmutate1 tc `EagerCall [f_concl; concl] @@ -543,8 +503,8 @@ let t_eager_r h inv tc = check_only_global !!tc env s'; let eC, c, c' = tc1_destr_eagerS tc s s' in - let eqinv = Mpv2.of_form env mleft mright inv in - let eqO = Mpv2.of_form env mleft mright eC.es_po in + let eqinv = Mpv2.of_form env inv in + let eqO = Mpv2.of_form env (es_po eC) in let c1, c1', fhyps, eqi = eager !!tc env s s' eqinv eqIs eqXs c c' eqO in if c1 <> [] || c1' <> [] then @@ -554,22 +514,19 @@ let t_eager_r h inv tc = let defl = Fun.by_xpath fl env in let defr = Fun.by_xpath fr env in let sigl, sigr = defl.f_sig, defr.f_sig in - let eq_res = f_eqres sigl.fs_ret mleft sigr.fs_ret mright in - let post = Mpv2.to_form mleft mright eqo eq_res in + let eq_res = ts_inv_eqres sigl.fs_ret mleft sigr.fs_ret mright in + let post = Mpv2.to_form_ts_inv eqo eq_res in let eq_params = - f_eqparams + ts_inv_eqparams sigl.fs_arg sigl.fs_anames mleft sigr.fs_arg sigr.fs_anames mright in - let pre = f_and_simpl eq_params inv in + let pre = map_ts_inv2 f_and_simpl eq_params inv in f_eagerF pre s fl fr s' post in let concl = - f_equivS_r { eC with - es_sl = stmt []; es_sr = stmt []; - es_po = Mpv2.to_form mleft mright eqi f_true; - } - in + f_equivS (snd eC.es_ml) (snd eC.es_mr) (es_pr eC) (stmt []) (stmt []) + (Mpv2.to_form_ts_inv eqi {ml=mleft;mr=mright;inv=f_true}) in let concls = List.map dof fhyps in @@ -606,7 +563,7 @@ let process_info info tc = let eqXs = process_formula eqXs in let s1 = TTC.tc1_process_stmt tc (snd ml) s1 in let s2 = TTC.tc1_process_stmt tc (snd mr) s2 in - let f = f_equivS ml mr eqIs s1 s2 eqXs in + let f = f_equivS_old ml mr eqIs s1 s2 eqXs in let h = LDecl.fresh_id hyps (unloc h) in (FApi.t_last (t_intros_i [h]) (t_cut f tc), h) @@ -633,11 +590,12 @@ let process_fun_def tc = (* -------------------------------------------------------------------- *) let process_fun_abs info eqI tc = + let ml, mr = EcIdent.create "&1", EcIdent.create "&2" in let hyps = FApi.tc1_hyps tc in - let env = LDecl.inv_memenv hyps in + let env = LDecl.inv_memenv ml mr hyps in let eqI = TTC.pf_process_form !!tc env tbool eqI in let gs, h = process_info info tc in - FApi.t_last (t_eager_fun_abs eqI h) gs + FApi.t_last (t_eager_fun_abs {inv=eqI;ml;mr} h) gs (* -------------------------------------------------------------------- *) let process_call info tc = @@ -653,10 +611,11 @@ let process_call info tc = check_only_global !!tc env sl; check_only_global !!tc env sr; - let penv, qenv = LDecl.equivF fl fr hyps in + let (ml, mr) = (EcIdent.create "&1", EcIdent.create "&2") in + let penv, qenv = LDecl.equivF ml mr fl fr hyps in let fpre = TTC.pf_process_form !!tc penv tbool fpre in let fpost = TTC.pf_process_form !!tc qenv tbool fpost in - f_eagerF fpre sl fl fr sr fpost + f_eagerF {ml;mr;inv=fpre} sl fl fr sr {ml;mr;inv=fpost} | _ -> tc_error !!tc "invalid arguments" in @@ -666,14 +625,12 @@ let process_call info tc = let eg = pf_as_eagerF !!tc ax in FApi.t_on1seq 0 - (t_eager_call eg.eg_pr eg.eg_po) + (t_eager_call (eg_pr eg) (eg_po eg)) (EcLowGoal.Apply.t_apply_bwd_hi ~dpe:true pt) tc (* -------------------------------------------------------------------- *) let process_eager info inv tc = - let hyps = FApi.tc1_hyps tc in - let penv = LDecl.inv_memenv hyps in - let inv = TTC.pf_process_formula !!tc penv inv in + let inv = TTC.tc1_process_prhl_form tc tbool inv in let gs, h = process_info info tc in FApi.t_last (t_eager h inv) gs diff --git a/src/phl/ecPhlEager.mli b/src/phl/ecPhlEager.mli index b105deae2..1958df552 100644 --- a/src/phl/ecPhlEager.mli +++ b/src/phl/ecPhlEager.mli @@ -1,17 +1,17 @@ (* -------------------------------------------------------------------- *) open EcUtils open EcParsetree -open EcFol open EcCoreGoal.FApi open EcMatching.Position +open EcAst (* -------------------------------------------------------------------- *) -val t_eager_seq : codepos1 -> codepos1 -> form -> EcIdent.t -> backward +val t_eager_seq : codepos1 -> codepos1 -> ts_inv -> EcIdent.t -> backward val t_eager_if : backward val t_eager_while : EcIdent.t -> backward val t_eager_fun_def : backward -val t_eager_fun_abs : EcFol.form -> EcIdent.t -> backward -val t_eager_call : form -> form -> backward +val t_eager_fun_abs : ts_inv -> EcIdent.t -> backward +val t_eager_call : ts_inv -> ts_inv -> backward (* -------------------------------------------------------------------- *) val process_seq : eager_info -> pcodepos1 pair -> pformula -> backward diff --git a/src/phl/ecPhlEqobs.ml b/src/phl/ecPhlEqobs.ml index 311db4c14..7cc3fb3cc 100644 --- a/src/phl/ecPhlEqobs.ml +++ b/src/phl/ecPhlEqobs.ml @@ -42,7 +42,7 @@ let extend_body fsig body = (* Invariant ifvl,ifvr = PV.fv env ml inv, PV.fv env mr inv *) type sim = { sim_env : env; - sim_inv : form; + sim_inv : ts_inv; sim_ifvl : PV.t; sim_ifvr : PV.t; default_spec : EcPath.xpath -> EcPath.xpath -> Mpv2.t -> Mpv2.t; @@ -81,8 +81,8 @@ let init_sim env spec inv = { sim_env = env; sim_inv = inv; - sim_ifvl = PV.fv env mleft inv; - sim_ifvr = PV.fv env mright inv; + sim_ifvl = PV.fv env inv.ml inv.inv; + sim_ifvr = PV.fv env inv.mr inv.inv; default_spec = default_spec; needed_spec = []; } @@ -322,9 +322,9 @@ and f_eqobs_in fl fr sim eqO = aux eqo in begin try - let inv = Mpv2.to_form mleft mright eqi sim.sim_inv in - let fvl = PV.fv env mleft inv in - let fvr = PV.fv env mright inv in + let inv = Mpv2.to_form_ts_inv eqi sim.sim_inv in + let fvl = PV.fv env inv.ml inv.inv in + let fvr = PV.fv env inv.mr inv.inv in PV.check_depend env fvl topl; PV.check_depend env fvr topr with TcError _ -> raise EqObsInError @@ -359,6 +359,7 @@ and f_eqobs_in fl fr sim eqO = (* -------------------------------------------------------------------- *) let mk_inv_spec2 env inv (fl, fr, eqi, eqo) = + let ml, mr = inv.ml, inv.mr in let defl = Fun.by_xpath fl env in let defr = Fun.by_xpath fr env in let sigl, sigr = defl.f_sig, defr.f_sig in @@ -367,12 +368,12 @@ let mk_inv_spec2 env inv (fl, fr, eqi, eqo) = && EcReduction.EqTest.for_type env sigl.fs_ret sigr.fs_ret in if not testty then raise EqObsInError; let eq_params = - f_eqparams - sigl.fs_arg sigl.fs_anames mleft - sigr.fs_arg sigr.fs_anames mright in - let eq_res = f_eqres sigl.fs_ret mleft sigr.fs_ret mright in - let pre = f_and eq_params (Mpv2.to_form mleft mright eqi inv) in - let post = f_and eq_res (Mpv2.to_form mleft mright eqo inv) in + ts_inv_eqparams + sigl.fs_arg sigl.fs_anames ml + sigr.fs_arg sigr.fs_anames mr in + let eq_res = ts_inv_eqres sigl.fs_ret ml sigr.fs_ret mr in + let pre = map_ts_inv2 f_and eq_params (Mpv2.to_form_ts_inv eqi inv) in + let post = map_ts_inv2 f_and eq_res (Mpv2.to_form_ts_inv eqo inv) in f_equivF pre fl fr post (* -------------------------------------------------------------------- *) @@ -384,21 +385,20 @@ let t_eqobs_inS_r sim eqo tc = let env, hyps, _ = FApi.tc1_eflat tc in let sim = { sim with sim_env = env } in let es = tc1_as_equivS tc in - let ml = fst (es.es_ml) and mr = fst (es.es_mr) in let sl, sr, sim, eqi = try s_eqobs_in es.es_sl es.es_sr sim Mpv2.empty_local eqo with EqObsInError -> tc_error !!tc "cannot apply sim ..." in let inv = sim.sim_inv in - let post = Mpv2.to_form ml mr eqo inv in - let pre = Mpv2.to_form ml mr eqi inv in + let post = Mpv2.to_form_ts_inv eqo inv in + let pre = Mpv2.to_form_ts_inv eqi inv in let sl = stmt (List.rev sl) and sr = stmt (List.rev sr) in - if not (EcReduction.is_alpha_eq hyps post es.es_po) then + if not (EcReduction.ts_inv_alpha_eq hyps post (es_po es)) then tc_error !!tc "cannot apply sim"; let sg = List.map (mk_inv_spec env inv) sim.needed_spec in - let concl = f_equivS es.es_ml es.es_mr es.es_pr sl sr pre in + let concl = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl sr pre in FApi.xmutate1 tc `EqobsIn (sg @ [concl]) @@ -426,40 +426,40 @@ let t_eqobs_inF = FApi.t_low2 "eqobs-in" t_eqobs_inF_r (* -------------------------------------------------------------------- *) let process_eqs env tc f = try - Mpv2.of_form env mleft mright f + Mpv2.of_form env f with Not_found -> tc_error_lazy !!tc (fun fmt -> let ppe = EcPrinting.PPEnv.ofenv env in Format.fprintf fmt "cannot recognize %a as a set of equalities" - (EcPrinting.pp_form ppe) f) + (EcPrinting.pp_form ppe) f.inv) (* -------------------------------------------------------------------- *) -let process_hint tc hyps (feqs, inv) = +let process_hint ml mr tc hyps (feqs, inv) = let env = LDecl.toenv hyps in - let ienv = LDecl.inv_memenv hyps in - let doinv pf = TTC.pf_process_form !!tc ienv tbool pf in + let doinv pf = TTC.tc1_process_prhl_form tc tbool pf in let doeq pf = process_eqs env tc (doinv pf) in let dof g = omap (EcTyping.trans_gamepath env) g in let geqs = List.map (fun ((f1,f2),geq) -> dof f1, dof f2, doeq geq) feqs in - let ginv = odfl f_true (omap doinv inv) in + let ginv = odfl {ml;mr;inv=f_true} (omap doinv inv) in geqs, ginv (* -------------------------------------------------------------------- *) let process_eqobs_inS info tc = let env, hyps, _ = FApi.tc1_eflat tc in let es = tc1_as_equivS tc in - let spec, inv = process_hint tc hyps info.EcParsetree.sim_hint in + let ml, mr = fst es.es_ml, fst es.es_mr in + let spec, inv = process_hint ml mr tc hyps info.EcParsetree.sim_hint in let eqo = match info.EcParsetree.sim_eqs with | Some pf -> process_eqs env tc (TTC.tc1_process_prhl_formula tc pf) | None -> - try Mpv2.needed_eq env mleft mright es.es_po - with _ -> tc_error !!tc "cannot infer the set of equalities" in - let post = Mpv2.to_form mleft mright eqo inv in + try Mpv2.needed_eq env (es_po es) + with Not_found -> tc_error !!tc "cannot infer the set of equalities" in + let post = Mpv2.to_form_ts_inv eqo inv in let sim = init_sim env spec inv in let t_main tc = match info.EcParsetree.sim_pos with @@ -475,14 +475,14 @@ let process_eqobs_inS info tc = let _, eqi = try s_eqobs_in_full (stmt sl2) (stmt sr2) sim Mpv2.empty_local eqo with EqObsInError -> tc_error !!tc "cannot apply sim" in - (EcPhlApp.t_equiv_app (p1, p2) (Mpv2.to_form mleft mright eqi inv) @+ [ + (EcPhlApp.t_equiv_app (p1, p2) (Mpv2.to_form_ts_inv eqi inv) @+ [ t_id; fun tc -> FApi.t_last (EcPhlSkip.t_skip @! t_trivial) (t_eqobs_inS sim eqo tc) ]) tc in - (EcPhlConseq.t_equivS_conseq es.es_pr post @+ + (EcPhlConseq.t_equivS_conseq (es_pr es) post @+ [t_trivial; t_trivial; t_main]) tc @@ -493,16 +493,15 @@ let process_eqobs_inF info tc = tc_error !!tc "no positions excepted"; let env, hyps, _ = FApi.tc1_eflat tc in let ef = tc1_as_equivF tc in - let spec, inv = process_hint tc hyps info.EcParsetree.sim_hint in + let ml, mr = ef.ef_ml, ef.ef_mr in + let spec, inv = process_hint ml mr tc hyps info.EcParsetree.sim_hint in let fl = ef.ef_fl and fr = ef.ef_fr in let eqo = match info.EcParsetree.sim_eqs with | Some pf -> - let _,(ml,mr) = Fun.equivF_memenv fl fr env in - let hyps = LDecl.push_all [ml;mr] hyps in - process_eqs env tc (TTC.pf_process_form !!tc hyps tbool pf) + process_eqs env tc (TTC.tc1_process_prhl_form tc tbool pf) | None -> - try Mpv2.needed_eq env mleft mright ef.ef_po + try Mpv2.needed_eq env (ef_po ef) with _ -> tc_error !!tc "cannot infer the set of equalities" in let eqo = Mpv2.remove env pv_res pv_res eqo in let sim = init_sim env spec inv in @@ -510,7 +509,7 @@ let process_eqobs_inF info tc = try f_eqobs_in fl fr sim eqo with EqObsInError -> tc_error !!tc "not able to process" in let ef' = destr_equivF (mk_inv_spec2 env inv (fl, fr, eqi, eqo)) in - (EcPhlConseq.t_equivF_conseq ef'.ef_pr ef'.ef_po @+ [ + (EcPhlConseq.t_equivF_conseq (ef_pr ef') (ef_po ef') @+ [ t_trivial; t_trivial; t_eqobs_inF sim eqo]) tc @@ -520,7 +519,6 @@ let process_eqobs_in cm info tc = let prett cm tc = let dt, ts = EcHiGoal.process_crushmode cm in EcPhlConseq.t_conseqauto ~delta:dt ?tsolve:ts tc in - let tt tc = let concl = FApi.tc1_goal tc in match concl.f_node with diff --git a/src/phl/ecPhlExists.ml b/src/phl/ecPhlExists.ml index c0b4bab2b..03e25cdeb 100644 --- a/src/phl/ecPhlExists.ml +++ b/src/phl/ecPhlExists.ml @@ -3,6 +3,7 @@ open EcUtils open EcAst open EcFol open EcEnv +open EcSubst open EcCoreGoal open EcLowGoal @@ -15,10 +16,11 @@ module PT = EcProofTerm (* -------------------------------------------------------------------- *) let get_to_gens fs = - let do_id f = + let do_id (f: inv) = let id = - match f.f_node with - | Fpvar (pv, m) -> id_of_pv pv m + match (inv_of_inv f).f_node with + | Fpvar (pv, m) -> + id_of_pv pv m | _ -> EcIdent.create "f" in id, f in List.map do_id fs @@ -26,9 +28,10 @@ let get_to_gens fs = (* -------------------------------------------------------------------- *) let t_hr_exists_elim_r ?(bound : int option) (tc : tcenv1) = let pre = tc1_get_pre tc in - let bd, pre = - try destr_exists_prenex ?bound pre - with DestrError _ -> [], pre in + let bd, pre' = + try destr_exists_prenex ?bound (inv_of_inv pre) + with DestrError _ -> [], (inv_of_inv pre) in + let pre = map_inv1 (fun _ -> pre') pre in let concl = f_forall bd (set_pre ~pre (FApi.tc1_goal tc)) in FApi.xmutate1 tc `HlExists [concl] @@ -38,38 +41,34 @@ let t_hr_exists_intro_r fs tc = let concl = FApi.tc1_goal tc in let pre1 = tc1_get_pre tc in let post = tc1_get_post tc in - let side = is_equivS concl || is_equivF concl in let gen = get_to_gens fs in - let eqs = List.map (fun (id, f) -> f_eq (f_local id f.f_ty) f) gen in - let bd = List.map (fun (id, f) -> (id, GTty f.f_ty)) gen in + let eqs = List.map (fun (id, f) -> map_inv1 (f_eq (f_local id (inv_of_inv f).f_ty)) f) gen in + let bd = List.map (fun (id, f) -> (id, GTty (inv_of_inv f).f_ty)) gen in let is_ehoare = match concl.f_node with | FeHoareF _ | FeHoareS _ -> true | _ -> false in let pre = if is_ehoare then - f_interp_ehoare_form (f_exists bd (f_ands eqs)) pre1 - else f_exists bd (f_and (f_ands eqs) pre1) in + map_inv2 f_interp_ehoare_form (map_inv1 (f_exists bd) (map_inv f_ands eqs)) pre1 + else + map_inv1 (f_exists bd) (map_inv2 f_and (map_inv f_ands eqs) pre1) in let h = LDecl.fresh_id hyps "h" in - let ms, subst = - match side with - | true -> - let ml, mr = as_seq2 (LDecl.fresh_ids hyps ["&ml"; "&mr"]) in - let s = Fsubst.f_subst_id in - let s = Fsubst.f_bind_mem s mleft ml in - let s = Fsubst.f_bind_mem s mright mr in - ([ml; mr], s) - - | false -> - let m = LDecl.fresh_id hyps "&m" in - let s = Fsubst.f_subst_id in - let s = Fsubst.f_bind_mem s mhr m in - ([m], s) - in + let ml, mr = as_seq2 (LDecl.fresh_ids hyps ["&ml"; "&mr"]) in + let m = LDecl.fresh_id hyps "&m" in + let ms = + match List.hd gen with + | (_, Inv_ts _) -> [ml; mr] + | (_, Inv_ss _) -> [m] in + + let inv_rebind f = + match f with + | Inv_ts f -> Inv_ts (ts_inv_rebind f ml mr) + | Inv_ss f -> Inv_ss (ss_inv_rebind f m) in let args = - let do1 (_, f) = PAFormula (Fsubst.f_subst subst f) in + let do1 (_, f) = PAFormula (inv_of_inv (inv_rebind f)) in List.map do1 gen in @@ -97,22 +96,24 @@ let t_hr_exists_intro = FApi.t_low1 "hr-exists-intro" t_hr_exists_intro_r (* -------------------------------------------------------------------- *) let process_exists_intro ~(elim : bool) fs tc = let (hyps, concl) = FApi.tc1_flat tc in - let penv = + let penv, f_tr = match concl.f_node with - | FhoareF hf -> fst (LDecl.hoareF hf.hf_f hyps) - | FhoareS hs -> LDecl.push_active hs.hs_m hyps - | FeHoareF hf -> fst (LDecl.hoareF hf.ehf_f hyps) - | FeHoareS hs -> LDecl.push_active hs.ehs_m hyps - | FbdHoareF bhf -> fst (LDecl.hoareF bhf.bhf_f hyps) - | FbdHoareS bhs -> LDecl.push_active bhs.bhs_m hyps - | FequivF ef -> fst (LDecl.equivF ef.ef_fl ef.ef_fr hyps) - | FequivS es -> LDecl.push_all [es.es_ml; es.es_mr] hyps + | FhoareF {hf_f=f;hf_m=m} | FeHoareF {ehf_f=f; ehf_m=m} + | FbdHoareF {bhf_f=f; bhf_m=m} -> + fst (LDecl.hoareF m f hyps), Inv_ss {m; inv = f_true} + | FhoareS {hs_m=(m,_) as me} | FeHoareS {ehs_m=(m,_) as me} + | FbdHoareS {bhs_m=(m,_) as me} -> + LDecl.push_active_ss me hyps, Inv_ss {m; inv = f_true} + | FequivF ef -> fst (LDecl.equivF ef.ef_ml ef.ef_mr ef.ef_fl ef.ef_fr hyps), + Inv_ts {ml=ef.ef_ml; mr=ef.ef_mr; inv=f_true} + | FequivS es -> LDecl.push_all [es.es_ml; es.es_mr] hyps, + Inv_ts {ml=(fst es.es_ml); mr=(fst es.es_mr); inv=f_true} | _ -> tc_error_noXhl ~kinds:hlkinds_Xhl !!tc in let fs = List.map - (fun f -> TTC.pf_process_form_opt !!tc penv None f) + (fun f -> map_inv1 (fun _ -> TTC.pf_process_form_opt !!tc penv None f) f_tr) fs in @@ -126,41 +127,44 @@ let process_exists_intro ~(elim : bool) fs tc = let process_ecall oside (l, tvi, fs) tc = let (hyps, concl) = FApi.tc1_flat tc in - let hyps, kind = + let hyps, kind, f_tr = match concl.f_node with | FhoareS hs when is_none oside -> - (LDecl.push_active hs.hs_m hyps, `Hoare (List.length hs.hs_s.s_node)) + LDecl.push_active_ss hs.hs_m hyps, `Hoare (List.length hs.hs_s.s_node), + Inv_ss {m = fst hs.hs_m; inv = f_true} | FequivS es -> let n1 = List.length es.es_sl.s_node in let n2 = List.length es.es_sr.s_node in - (LDecl.push_all [es.es_ml; es.es_mr] hyps, `Equiv (n1, n2)) + LDecl.push_all [es.es_ml; es.es_mr] hyps, `Equiv (n1, n2), + Inv_ts {ml = fst es.es_ml; mr = fst es.es_mr; inv = f_true} | _ -> tc_error_noXhl ~kinds:[`Hoare `Stmt; `Equiv `Stmt] !!tc in let t_local_seq p1 tc = - match kind, oside with - | `Hoare n, _ -> + match kind, oside, p1 with + | `Hoare n, _, Inv_ss p1 -> EcPhlApp.t_hoare_app (Zpr.cpos (n-1)) p1 tc - | `Equiv (n1, n2), None -> + | `Equiv (n1, n2), None, Inv_ts p1 -> EcPhlApp.t_equiv_app (Zpr.cpos (n1-1), Zpr.cpos (n2-1)) p1 tc - | `Equiv (n1, n2), Some `Left -> + | `Equiv (n1, n2), Some `Left, Inv_ts p1 -> EcPhlApp.t_equiv_app (Zpr.cpos (n1-1), Zpr.cpos n2) p1 tc - | `Equiv(n1, n2), Some `Right -> + | `Equiv(n1, n2), Some `Right, Inv_ts p1 -> EcPhlApp.t_equiv_app (Zpr.cpos n1, Zpr.cpos (n2-1)) p1 tc + | _ -> tc_error !!tc "mismatched sidedness or kind of conclusion" in let fs = List.map - (fun f -> TTC.pf_process_form_opt !!tc hyps None f) + (fun f -> map_inv1 (fun _ -> TTC.pf_process_form_opt !!tc hyps None f) f_tr) fs in let ids, p1 = - let sub = t_local_seq f_true tc in + let sub = t_local_seq f_tr tc in let sub = FApi.t_rotate `Left 1 sub in let sub = FApi.t_focus (t_hr_exists_intro_r fs) sub in @@ -190,10 +194,10 @@ let process_ecall oside (l, tvi, fs) tc = let subst = List.fold_left2 - (fun s id f -> Fsubst.f_bind_local s id f) - Fsubst.f_subst_id (List.fst ids) fs in + (fun s id f -> add_flocal s id (inv_of_inv f)) + empty (List.fst ids) fs in - (nms, Fsubst.f_subst subst sub) in + (nms, subst_inv subst sub) in let tc = t_local_seq p1 tc in let tc = FApi.t_rotate `Left 1 tc in diff --git a/src/phl/ecPhlExists.mli b/src/phl/ecPhlExists.mli index edcaa8758..685af80a7 100644 --- a/src/phl/ecPhlExists.mli +++ b/src/phl/ecPhlExists.mli @@ -1,12 +1,12 @@ (* -------------------------------------------------------------------- *) open EcParsetree -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) val t_hr_exists_elim_r : ?bound:int -> backward val t_hr_exists_elim : backward -val t_hr_exists_intro : form list -> backward +val t_hr_exists_intro : inv list -> backward (* -------------------------------------------------------------------- *) val process_exists_intro : elim:bool -> pformula list -> backward diff --git a/src/phl/ecPhlFel.ml b/src/phl/ecPhlFel.ml index 0bfdfbb7a..8d4e44c34 100644 --- a/src/phl/ecPhlFel.ml +++ b/src/phl/ecPhlFel.ml @@ -124,19 +124,19 @@ let t_failure_event_r (at_pos, cntr, ash, q, f_event, pred_specs, inv) tc = | _ -> tc_error !!tc "a goal of the form Pr[ _ ] <= _ is required" in - let m = oget (Memory.byid pr.pr_mem env) in + let pr_m = oget (Memory.byid pr.pr_mem env) in let f = NormMp.norm_xfun env pr.pr_fun in let ev = pr.pr_event in let memenv, (fsig, fdef), _ = - try Fun.hoareS f env + try Fun.hoareS ev.m f env with _ -> tc_error !!tc "not applicable to abstract functions" in let s_hd, s_tl = EcLowPhlGoal.s_split env at_pos fdef.f_body in - let fve = PV.fv env mhr f_event in - let fvc = PV.fv env mhr cntr in - let fvi = PV.fv env mhr inv in + let fve = PV.fv env f_event.m f_event.inv in + let fvc = PV.fv env cntr.m cntr.inv in + let fvi = PV.fv env inv.m inv.inv in let fv = PV.union (PV.union fve fvc) fvi in let os = callable_oracles_stmt env fv (stmt s_tl) in @@ -157,12 +157,15 @@ let t_failure_event_r (at_pos, cntr, ash, q, f_event, pred_specs, inv) tc = in (* we must quantify over memories *) - let mo = EcIdent.create "&m" in let post_goal = - let subst = Fsubst.f_bind_mem Fsubst.f_subst_id mhr mo in - let p = f_imps [ev;inv] (f_and f_event (f_int_le cntr q)) in - let p = Fsubst.f_subst subst p in - f_forall_mems [mo, EcMemory.memtype m] p + let lev = map_ss_inv2 f_and f_event (map_ss_inv1 (fun cnt -> f_int_le cnt q) cntr) in + let m = (EcIdent.create "&hr", snd pr_m) in + let lev = EcSubst.ss_inv_rebind lev (fst m) in + let ev = EcSubst.ss_inv_rebind ev (fst m) in + let inv = EcSubst.ss_inv_rebind inv (fst m) in + let f_imps' l = f_imps (List.tl l) (List.hd l) in + let p = map_ss_inv f_imps' [lev;ev;inv] in + EcSubst.f_forall_mems_ss_inv m p in (* not fail and cntr=0 and invariant holds at designated program point, @@ -172,20 +175,21 @@ let t_failure_event_r (at_pos, cntr, ash, q, f_event, pred_specs, inv) tc = let init_goal = let xs,gs = PV.ntr_elements (f_read env f) in - let mh = fst memenv in - let mi = pr.pr_mem in - let f_xeq (x,ty) = f_eq (f_pvar x ty mh) (f_pvar x ty mi) in + let m = fst memenv in + let pr_m = pr.pr_mem in + let f_xeq (x,ty) = map_ss_inv2 f_eq (f_pvar x ty m) {m;inv=(f_pvar x ty pr_m).inv} in let eqxs = List.map f_xeq xs in - let eqgs = List.map (fun m -> f_eqglob m mh m mi) gs in + let eqgs = List.map (fun m' -> {m;inv=f_eqglob m' m m' pr_m}) gs in let eqparams = let vs = fsig.fs_anames in let var_of_ovar ov = { v_name = oget ov.ov_name; v_type = ov.ov_type } in - let f_x x = assert (is_some x.ov_name); f_pvloc (var_of_ovar x) mh in - f_eq (f_tuple (List.map f_x vs)) pr.pr_args in - let pre = f_ands (eqparams :: (eqxs@eqgs)) in - let p = f_and (f_not f_event) (f_eq cntr f_i0) in - let p = f_and_simpl p inv in - f_hoareS memenv pre (stmt s_hd) p + let f_x x = assert (is_some x.ov_name); (f_pvloc (var_of_ovar x) m) in + map_ss_inv2 f_eq (map_ss_inv ~m f_tuple (List.map f_x vs)) {m;inv=pr.pr_args} in + let pre = map_ss_inv f_ands (eqparams :: (eqxs@eqgs)) in + let p = map_ss_inv2 f_and (map_ss_inv1 f_not f_event) (map_ss_inv2 f_eq cntr {m=cntr.m;inv=f_i0}) in + let p = map_ss_inv2 f_and_simpl p inv in + let p = EcSubst.ss_inv_rebind p pre.m in + f_hoareS (snd memenv) pre (stmt s_hd) p in let oracle_goal o = @@ -193,15 +197,15 @@ let t_failure_event_r (at_pos, cntr, ash, q, f_event, pred_specs, inv) tc = pred_specs |> List.ofind (fun (o', _) -> o = o') |> omap snd - |> odfl f_true + |> odfl {m=f_event.m; inv=f_true} in let not_F_to_F_goal = - let bound = f_app_simpl ash [cntr] treal in - let pre = f_and (f_int_le f_i0 cntr) (f_int_lt cntr q) in - let pre = f_and pre (f_not f_event) in - let pre = f_and_simpl pre inv in - let pre = f_and_simpl pre some_p in + let bound = map_ss_inv1 (fun cn -> f_app_simpl ash [cn] treal) cntr in + let pre = map_ss_inv1 (fun cn -> f_and (f_int_le f_i0 cn) (f_int_lt cn q)) cntr in + let pre = map_ss_inv2 f_and pre (map_ss_inv1 f_not f_event) in + let pre = map_ss_inv2 f_and_simpl pre inv in + let pre = map_ss_inv2 f_and_simpl pre some_p in let post = f_event in f_bdHoareF pre o post FHle bound in @@ -211,17 +215,23 @@ let t_failure_event_r (at_pos, cntr, ash, q, f_event, pred_specs, inv) tc = let old_b = f_local old_b_id tbool in let cntr_decr_goal = - let pre = f_and some_p (f_eq old_cntr cntr) in - let pre = f_and_simpl pre inv in - let post = f_int_lt old_cntr cntr in - let post = f_and_simpl post inv in + let old_cntr = {m=cntr.m;inv=old_cntr} in + let pre = map_ss_inv2 f_and some_p (map_ss_inv2 f_eq old_cntr cntr) in + let pre = map_ss_inv2 f_and_simpl pre inv in + let post = map_ss_inv2 f_int_lt old_cntr cntr in + let post = map_ss_inv2 f_and_simpl post inv in f_forall_simpl [old_cntr_id,GTty tint] (f_hoareF pre o post) in let cntr_stable_goal = - let pre = f_ands [f_not some_p;f_eq f_event old_b;f_eq cntr old_cntr] in - let pre = f_and_simpl pre inv in - let post = f_ands [f_eq f_event old_b;f_int_le old_cntr cntr] in - let post = f_and_simpl post inv in + let old_cntr = {m=cntr.m;inv=old_cntr} in + let old_b = {m=cntr.m;inv=old_b} in + let pre = map_ss_inv f_ands [ + map_ss_inv1 f_not some_p; + map_ss_inv2 f_eq f_event old_b; + map_ss_inv2 f_eq cntr old_cntr] in + let pre = map_ss_inv2 f_and_simpl pre inv in + let post = map_ss_inv f_ands [map_ss_inv2 f_eq f_event old_b; map_ss_inv2 f_int_le old_cntr cntr] in + let post = map_ss_inv2 f_and_simpl post inv in f_forall_simpl [old_b_id,GTty tbool; old_cntr_id,GTty tint] (f_hoareF pre o post) @@ -256,24 +266,26 @@ let process_fel at_pos (infos : fel_info) tc = -> destr_pr pr | _ -> tc_error !!tc "a goal of the form Pr[ _ ] <= _ is required" in + + let m = EcIdent.create "&hr" in let at_pos = EcTyping.trans_codepos1 env at_pos in - let hyps = LDecl.inv_memenv1 hyps1 in - let cntr = TTC.pf_process_form !!tc hyps tint infos.pfel_cntr in - let ash = TTC.pf_process_form !!tc hyps (tfun tint treal) infos.pfel_asg in - let hypsq = LDecl.push_active (EcMemory.abstract pr.pr_mem) hyps1 in + let hyps = LDecl.inv_memenv1 m hyps1 in + let cntr = {m;inv=TTC.pf_process_form !!tc hyps tint infos.pfel_cntr} in + let hypsq = LDecl.push_active_ss (EcMemory.abstract pr.pr_mem) hyps1 in + let ash = TTC.pf_process_form !!tc hypsq (tfun tint treal) infos.pfel_asg in let q = TTC.pf_process_form !!tc hypsq tint infos.pfel_q in - let f_event = TTC.pf_process_form !!tc hyps tbool infos.pfel_event in + let f_event = {m;inv=TTC.pf_process_form !!tc hyps tbool infos.pfel_event} in let inv = infos.pfel_inv - |> omap (fun inv -> TTC.pf_process_form !!tc hyps tbool inv) - |> odfl f_true + |> omap (fun inv -> {m;inv=TTC.pf_process_form !!tc hyps tbool inv}) + |> odfl {m;inv=f_true} in let process_pred (f,pre) = let env = LDecl.toenv hyps in let f = EcTyping.trans_gamepath env f in - let penv = fst (LDecl.hoareF f hyps) in - (f, TTC.pf_process_form !!tc penv tbool pre) + let penv = fst (LDecl.hoareF m f hyps) in + (f, {m;inv=TTC.pf_process_form !!tc penv tbool pre}) in let pred_specs = List.map process_pred infos.pfel_specs in diff --git a/src/phl/ecPhlFel.mli b/src/phl/ecPhlFel.mli index 283d4b2a7..e6769715a 100644 --- a/src/phl/ecPhlFel.mli +++ b/src/phl/ecPhlFel.mli @@ -1,16 +1,16 @@ (* -------------------------------------------------------------------- *) open EcPath open EcParsetree -open EcFol +open EcAst open EcCoreGoal.FApi open EcMatching.Position (* -------------------------------------------------------------------- *) val t_failure_event : codepos1 - -> form -> form -> form -> form - -> (xpath * form) list - -> form + -> ss_inv -> form -> form -> ss_inv + -> (xpath * ss_inv) list + -> ss_inv -> backward (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlFun.ml b/src/phl/ecPhlFun.ml index 98120db7c..c0f04e6d7 100644 --- a/src/phl/ecPhlFun.ml +++ b/src/phl/ecPhlFun.ml @@ -9,6 +9,7 @@ open EcMemory open EcModules open EcEnv open EcPV +open EcSubst open EcCoreGoal open EcLowPhlGoal @@ -67,7 +68,7 @@ let subst_pre env fs (m : memory) s = | Some v -> { v_name = v; v_type = ov.ov_type } in let v = List.map (fun v -> f_pvloc (fresh v) m) fs.fs_anames in - PVM.add env pv_arg m (f_tuple v) s + PVM.add env pv_arg m (map_ss_inv ~m f_tuple v).inv s (* ------------------------------------------------------------------ *) let t_hoareF_fun_def_r tc = @@ -75,12 +76,12 @@ let t_hoareF_fun_def_r tc = let hf = tc1_as_hoareF tc in let f = NormMp.norm_xfun env hf.hf_f in check_concrete !!tc env f; - let (memenv, (fsig, fdef), env) = Fun.hoareS f env in + let (memenv, (fsig, fdef), env) = Fun.hoareS hf.hf_m f env in let m = EcMemory.memory memenv in - let fres = odfl f_tt (omap (form_of_expr m) fdef.f_ret) in - let post = PVM.subst1 env pv_res m fres hf.hf_po in - let pre = PVM.subst env (subst_pre env fsig m PVM.empty) hf.hf_pr in - let concl' = f_hoareS memenv pre fdef.f_body post in + let fres = odfl {m;inv=f_tt} (omap (ss_inv_of_expr m) fdef.f_ret) in + let post = map_ss_inv2 (PVM.subst1 env pv_res m) fres (hf_po hf) in + let pre = map_ss_inv1 (PVM.subst env (subst_pre env fsig m PVM.empty)) (hf_pr hf) in + let concl' = f_hoareS (snd memenv) pre fdef.f_body post in FApi.xmutate1 tc `FunDef [concl'] (* ------------------------------------------------------------------ *) @@ -89,12 +90,12 @@ let t_ehoareF_fun_def_r tc = let hf = tc1_as_ehoareF tc in let f = NormMp.norm_xfun env hf.ehf_f in check_concrete !!tc env f; - let (memenv, (fsig, fdef), env) = Fun.hoareS f env in + let (memenv, (fsig, fdef), env) = Fun.hoareS hf.ehf_m f env in let m = EcMemory.memory memenv in - let fres = odfl f_tt (omap (form_of_expr m) fdef.f_ret) in - let post = PVM.subst1 env pv_res m fres hf.ehf_po in - let pre = PVM.subst env (subst_pre env fsig m PVM.empty) hf.ehf_pr in - let concl' = f_eHoareS memenv pre fdef.f_body post in + let fres = odfl {m;inv=f_tt} (omap (ss_inv_of_expr m) fdef.f_ret) in + let post = map_ss_inv2 (PVM.subst1 env pv_res m) fres (ehf_po hf) in + let pre = map_ss_inv1 (PVM.subst env (subst_pre env fsig m PVM.empty)) (ehf_pr hf) in + let concl' = f_eHoareS (snd memenv) pre fdef.f_body post in FApi.xmutate1 tc `FunDef [concl'] (* ------------------------------------------------------------------ *) @@ -103,37 +104,36 @@ let t_bdhoareF_fun_def_r tc = let bhf = tc1_as_bdhoareF tc in let f = NormMp.norm_xfun env bhf.bhf_f in check_concrete !!tc env f; - let (memenv, (fsig, fdef), env) = Fun.hoareS f env in + let (memenv, (fsig, fdef), env) = Fun.hoareS bhf.bhf_m f env in let m = EcMemory.memory memenv in - let fres = odfl f_tt (omap (form_of_expr m) fdef.f_ret) in - let post = PVM.subst1 env pv_res m fres bhf.bhf_po in + let fres = odfl {m;inv=f_tt} (omap (ss_inv_of_expr m) fdef.f_ret) in + let post = map_ss_inv2 (PVM.subst1 env pv_res m) fres (bhf_po bhf) in let spre = subst_pre env fsig m PVM.empty in - let pre = PVM.subst env spre bhf.bhf_pr in - let bd = PVM.subst env spre bhf.bhf_bd in - let concl' = f_bdHoareS memenv pre fdef.f_body post bhf.bhf_cmp bd in + let pre = map_ss_inv1 (PVM.subst env spre) (bhf_pr bhf) in + let bd = map_ss_inv1 (PVM.subst env spre) (bhf_bd bhf) in + let concl' = f_bdHoareS (snd memenv) pre fdef.f_body post bhf.bhf_cmp bd in FApi.xmutate1 tc `FunDef [concl'] (* ------------------------------------------------------------------ *) let t_equivF_fun_def_r tc = let env = FApi.tc1_env tc in let ef = tc1_as_equivF tc in + let ml, mr = ef.ef_ml, ef.ef_mr in let fl = NormMp.norm_xfun env ef.ef_fl in let fr = NormMp.norm_xfun env ef.ef_fr in check_concrete !!tc env fl; check_concrete !!tc env fr; - let (menvl, eqsl, menvr, eqsr, env) = Fun.equivS fl fr env in + let (menvl, eqsl, menvr, eqsr, env) = Fun.equivS ml mr fl fr env in let (fsigl, fdefl) = eqsl in let (fsigr, fdefr) = eqsr in - let ml = EcMemory.memory menvl in - let mr = EcMemory.memory menvr in - let fresl = odfl f_tt (omap (form_of_expr ml) fdefl.f_ret) in - let fresr = odfl f_tt (omap (form_of_expr mr) fdefr.f_ret) in - let s = PVM.add env pv_res ml fresl PVM.empty in - let s = PVM.add env pv_res mr fresr s in - let post = PVM.subst env s ef.ef_po in + let fresl = odfl {m=ml;inv=f_tt} (omap (ss_inv_of_expr ml) fdefl.f_ret) in + let fresr = odfl {m=mr;inv=f_tt} (omap (ss_inv_of_expr mr) fdefr.f_ret) in + let s = PVM.add env pv_res ml fresl.inv PVM.empty in + let s = PVM.add env pv_res mr fresr.inv s in + let post = map_ts_inv1 (PVM.subst env s) (ef_po ef) in let s = subst_pre env fsigl ml PVM.empty in let s = subst_pre env fsigr mr s in - let pre = PVM.subst env s ef.ef_pr in - let concl' = f_equivS menvl menvr pre fdefl.f_body fdefr.f_body post in + let pre = map_ts_inv1 (PVM.subst env s) (ef_pr ef) in + let concl' = f_equivS (snd menvl) (snd menvr) pre fdefl.f_body fdefr.f_body post in FApi.xmutate1 tc `FunDef [concl'] (* -------------------------------------------------------------------- *) @@ -158,16 +158,16 @@ module FunAbsLow = struct (* ------------------------------------------------------------------ *) let hoareF_abs_spec _pf env f inv = let (top, _, oi, _) = EcLowPhlGoal.abstract_info env f in - let fv = PV.fv env mhr inv in + let fv = PV.fv env inv.m inv.inv in PV.check_depend env fv top; let ospec o = f_hoareF inv o inv in let sg = List.map ospec (OI.allowed oi) in (inv, inv, sg) (* ------------------------------------------------------------------ *) - let ehoareF_abs_spec _pf env f inv = + let ehoareF_abs_spec _pf env f (inv: ss_inv) = let (top, _, oi, _) = EcLowPhlGoal.abstract_info env f in - let fv = PV.fv env mhr inv in + let fv = PV.fv env inv.m inv.inv in PV.check_depend env fv top; let ospec o = f_eHoareF inv o inv in let sg = List.map ospec (OI.allowed oi) in @@ -176,28 +176,28 @@ module FunAbsLow = struct (* ------------------------------------------------------------------ *) let bdhoareF_abs_spec pf env f inv = let (top, _, oi, _) = EcLowPhlGoal.abstract_info env f in - let fv = PV.fv env mhr inv in + let fv = PV.fv env inv.m inv.inv in PV.check_depend env fv top; let ospec o = check_oracle_use pf env top o; - f_bdHoareF inv o inv FHeq f_r1 in + f_bdHoareF inv o inv FHeq {m=inv.m;inv=f_r1} in let sg = List.map ospec (OI.allowed oi) in (inv, inv, lossless_hyps env top f.x_sub :: sg) (* ------------------------------------------------------------------ *) - let equivF_abs_spec pf env fl fr inv = + let equivF_abs_spec pf env fl fr (inv: ts_inv) = let (topl, _fl, oil, sigl), (topr, _fr, oir, sigr) = EcLowPhlGoal.abstract_info2 env fl fr in - let ml, mr = mleft, mright in - let fvl = PV.fv env ml inv in - let fvr = PV.fv env mr inv in + let ml, mr = inv.ml, inv.mr in + let fvl = PV.fv env inv.ml inv.inv in + let fvr = PV.fv env inv.mr inv.inv in PV.check_depend env fvl topl; PV.check_depend env fvr topr; - let eqglob = f_eqglob topl ml topr mr in + let eqglob = ts_inv_eqglob topl ml topr mr in let ospec o_l o_r = let use = @@ -221,8 +221,8 @@ module FunAbsLow = struct f_eqres fo_l.f_sig.fs_ret ml fo_r.f_sig.fs_ret mr in let invs = if use then [eqglob; inv] else [inv] in - let pre = EcFol.f_ands (eq_params :: invs) in - let post = EcFol.f_ands (eq_res :: invs) in + let pre = map_ts_inv (fun invs -> EcFol.f_ands (eq_params :: invs)) invs in + let post = map_ts_inv (fun invs -> EcFol.f_ands (eq_res :: invs)) invs in f_equivF pre o_l o_r post in @@ -233,10 +233,10 @@ module FunAbsLow = struct sigl.fs_arg sigl.fs_anames ml sigr.fs_arg sigr.fs_anames mr in - let eq_res = f_eqres sigl.fs_ret ml sigr.fs_ret mr in + let eq_res = ts_inv_eqres sigl.fs_ret ml sigr.fs_ret mr in let lpre = [eqglob;inv] in - let pre = f_ands (eq_params::lpre) in - let post = f_ands [eq_res; eqglob; inv] in + let pre = map_ts_inv (fun lpre -> f_ands (eq_params::lpre)) lpre in + let post = map_ts_inv f_ands [eq_res; eqglob; inv] in (pre, post, sg) end @@ -282,7 +282,7 @@ let t_equivF_abs_r inv tc = in let tactic tc = FApi.xmutate1 tc `FunAbs sg in - FApi.t_last tactic (EcPhlConseq.t_equivF_conseq pre post tc) + FApi.t_last tactic (EcPhlConseq.t_equivF_conseq pre post tc) (* -------------------------------------------------------------------- *) let t_hoareF_abs = FApi.t_low1 "hoare-fun-abs" t_hoareF_abs_r @@ -293,22 +293,23 @@ let t_equivF_abs = FApi.t_low1 "equiv-fun-abs" t_equivF_abs_r (* -------------------------------------------------------------------- *) module UpToLow = struct (* ------------------------------------------------------------------ *) - let equivF_abs_upto pf env fl fr bad invP invQ = + let equivF_abs_upto pf env fl fr (bad: ss_inv) (invP: ts_inv) (invQ: ts_inv) = let (topl, _fl, oil, sigl), (topr, _fr, oir, sigr) = EcLowPhlGoal.abstract_info2 env fl fr in - let ml, mr = mleft, mright in - let bad2 = Fsubst.f_subst_mem mhr mr bad in - let allinv = f_ands [bad2; invP; invQ] in - let fvl = PV.fv env ml allinv in - let fvr = PV.fv env mr allinv in + let ml, mr = invP.ml, invP.mr in + let bad = ss_inv_rebind bad invP.mr in + let bad2 = ss_inv_generalize_left bad invP.ml in + let allinv = map_ts_inv f_ands [bad2; invP; invQ] in + let fvl = PV.fv env ml allinv.inv in + let fvr = PV.fv env mr allinv.inv in PV.check_depend env fvl topl; PV.check_depend env fvr topr; (* FIXME: check there is only global variable *) - let eqglob = f_eqglob topl ml topr mr in + let eqglob = ts_inv_eqglob topl ml topr mr in let ospec o_l o_r = check_oracle_use pf env topl o_l; @@ -318,25 +319,25 @@ module UpToLow = struct let fo_l = EcEnv.Fun.by_xpath o_l env in let fo_r = EcEnv.Fun.by_xpath o_r env in let eq_params = - f_eqparams + ts_inv_eqparams fo_l.f_sig.fs_arg fo_l.f_sig.fs_anames ml fo_r.f_sig.fs_arg fo_r.f_sig.fs_anames mr in let eq_res = - f_eqres fo_l.f_sig.fs_ret ml fo_r.f_sig.fs_ret mr in + ts_inv_eqres fo_l.f_sig.fs_ret ml fo_r.f_sig.fs_ret mr in - let pre = EcFol.f_ands [EcFol.f_not bad2; eq_params; invP] in - let post = EcFol.f_if_simpl bad2 invQ (f_and eq_res invP) in + let pre = map_ts_inv EcFol.f_ands [map_ts_inv1 EcFol.f_not bad2; eq_params; invP] in + let post = map_ts_inv3 EcFol.f_if_simpl bad2 invQ (map_ts_inv2 f_and eq_res invP) in let cond1 = f_equivF pre o_l o_r post in let cond2 = - let q = Fsubst.f_subst_mem ml EcFol.mhr invQ in - f_forall[(mr, GTmem abstract_mt)] - (f_imp bad2 (f_bdHoareF q o_l q FHeq f_r1)) in + let f_r1 = {m=invQ.ml; inv=f_r1} in + let concl = ts_inv_lower_left1 (fun bq -> (f_bdHoareF bq o_l bq FHeq f_r1)) invQ in + f_forall_mems_ss_inv (mr, abstract_mt) + (map_ss_inv2 f_imp bad concl) in let cond3 = - let q = Fsubst.f_subst_mem mr EcFol.mhr invQ in - let bq = f_and bad q in - f_forall [(ml, GTmem abstract_mt)] - (f_bdHoareF bq o_r bq FHeq f_r1) in + let f_r1 = {m=invQ.mr; inv=f_r1} in + let bq = map_ts_inv2 f_and bad2 invQ in + f_forall_mems_ss_inv (ml, abstract_mt) (ts_inv_lower_right1 (fun bq -> f_bdHoareF bq o_r bq FHeq f_r1) bq) in [cond1; cond2; cond3] in @@ -347,15 +348,15 @@ module UpToLow = struct let sg = lossless_a :: sg in let eq_params = - f_eqparams + ts_inv_eqparams sigl.fs_arg sigl.fs_anames ml sigr.fs_arg sigr.fs_anames mr in - let eq_res = f_eqres sigl.fs_ret ml sigr.fs_ret mr in + let eq_res = ts_inv_eqres sigl.fs_ret ml sigr.fs_ret mr in let pre = [eqglob;invP] in - let pre = f_if_simpl bad2 invQ (f_ands (eq_params::pre)) in - let post = f_if_simpl bad2 invQ (f_ands [eq_res;eqglob;invP]) in + let pre = map_ts_inv3 f_if_simpl bad2 invQ (map_ts_inv f_ands (eq_params::pre)) in + let post = map_ts_inv3 f_if_simpl bad2 invQ (map_ts_inv f_ands [eq_res;eqglob;invP]) in (pre, post, sg) end @@ -404,13 +405,13 @@ module ToCodeLow = struct i_call (Some (LvVar (pv_loc (oget res.ov_name), res.ov_type)), f, eargs) in (me, stmt [icall], res, args) - let add_var env vfrom mfrom v me s = - PVM.add env vfrom mfrom (f_pvar (pv_loc (oget v.ov_name)) v.ov_type (fst me)) s + let add_var env vfrom mfrom v m s = + PVM.add env vfrom mfrom (f_pvar (pv_loc (oget v.ov_name)) v.ov_type m).inv s - let add_var_tuple env vfrom mfrom vs me s = + let add_var_tuple env vfrom mfrom vs m s = let vs = - List.map (fun v -> f_pvar (pv_loc v.v_name) v.v_type (fst me)) vs - in PVM.add env vfrom mfrom (f_tuple vs) s + List.map (fun v -> f_pvar (pv_loc v.v_name) v.v_type m) vs + in PVM.add env vfrom mfrom (map_ss_inv ~m f_tuple vs).inv s end (* -------------------------------------------------------------------- *) @@ -418,13 +419,14 @@ let t_fun_to_code_hoare_r tc = let env = FApi.tc1_env tc in let hf = tc1_as_hoareF tc in let f = hf.hf_f in - let m, st, r, a = ToCodeLow.to_code env f mhr in - let spr = ToCodeLow.add_var_tuple env pv_arg mhr a m PVM.empty in - let spo = ToCodeLow.add_var env pv_res mhr r m PVM.empty in - let pre = PVM.subst env spr hf.hf_pr in - let post = PVM.subst env spo hf.hf_po in - let concl = f_hoareS m pre st post in - + let m = hf.hf_m in + let (m0, mt), st, r, a = ToCodeLow.to_code env f m in + assert (EcIdent.id_equal m0 m); + let spr = ToCodeLow.add_var_tuple env pv_arg m a m PVM.empty in + let spo = ToCodeLow.add_var env pv_res m r m PVM.empty in + let pre = PVM.subst env spr (hf_pr hf).inv in + let post = PVM.subst env spo (hf_po hf).inv in + let concl = f_hoareS mt {m;inv=pre} st {m;inv=post} in FApi.xmutate1 tc `FunToCode [concl] (* -------------------------------------------------------------------- *) @@ -432,15 +434,16 @@ let t_fun_to_code_ehoare_r tc = let env = FApi.tc1_env tc in let hf = tc1_as_ehoareF tc in let f = hf.ehf_f in - let m, st, r, a = ToCodeLow.to_code env f mhr in - let spr = ToCodeLow.add_var_tuple env pv_arg mhr a m PVM.empty in - let spo = ToCodeLow.add_var env pv_res mhr r m PVM.empty in + let m = hf.ehf_m in + let (m0, mt), st, r, a = ToCodeLow.to_code env f m in + assert (EcIdent.id_equal m0 m); + let spr = ToCodeLow.add_var_tuple env pv_arg m a m PVM.empty in + let spo = ToCodeLow.add_var env pv_res m r m PVM.empty in let pre = PVM.subst env spr hf.ehf_pr in let post = PVM.subst env spo hf.ehf_po in - - let concl = f_eHoareS m pre st post in + let concl = f_eHoareS mt {m;inv=pre} st {m;inv=post} in FApi.xmutate1 tc `FunToCode [concl] @@ -448,59 +451,67 @@ let t_fun_to_code_ehoare_r tc = let t_fun_to_code_bdhoare_r tc = let env = FApi.tc1_env tc in let hf = tc1_as_bdhoareF tc in + let m = hf.bhf_m in let f = hf.bhf_f in - let m, st, r, a = ToCodeLow.to_code env f mhr in - let spr = ToCodeLow.add_var_tuple env pv_arg mhr a m PVM.empty in - let spo = ToCodeLow.add_var env pv_res mhr r m PVM.empty in + let (m0, mt), st, r, a = ToCodeLow.to_code env f m in + assert (EcIdent.id_equal m0 m); + let spr = ToCodeLow.add_var_tuple env pv_arg m0 a m PVM.empty in + let spo = ToCodeLow.add_var env pv_res m0 r m PVM.empty in let pre = PVM.subst env spr hf.bhf_pr in let post = PVM.subst env spo hf.bhf_po in let bd = PVM.subst env spr hf.bhf_bd in - let concl = f_bdHoareS m pre st post hf.bhf_cmp bd in + let concl = f_bdHoareS mt {m;inv=pre} st {m;inv=post} hf.bhf_cmp {m;inv=bd} in FApi.xmutate1 tc `FunToCode [concl] (* -------------------------------------------------------------------- *) let t_fun_to_code_equiv_r tc = let env = FApi.tc1_env tc in let ef = tc1_as_equivF tc in + let ml, mr = ef.ef_ml, ef.ef_mr in let (fl,fr) = ef.ef_fl, ef.ef_fr in - let ml, sl, rl, al = ToCodeLow.to_code env fl mleft in - let mr, sr, rr, ar = ToCodeLow.to_code env fr mright in + let (ml0, mlt), sl, rl, al = ToCodeLow.to_code env fl ml in + assert (EcIdent.id_equal ml0 ml); + let (mr0, mrt), sr, rr, ar = ToCodeLow.to_code env fr mr in + assert (EcIdent.id_equal mr0 mr); let spr = let s = PVM.empty in - let s = ToCodeLow.add_var_tuple env pv_arg mleft al ml s in - let s = ToCodeLow.add_var_tuple env pv_arg mright ar mr s in + let s = ToCodeLow.add_var_tuple env pv_arg ml al ml s in + let s = ToCodeLow.add_var_tuple env pv_arg mr ar mr s in s in let spo = let s = PVM.empty in - let s = ToCodeLow.add_var env pv_res mleft rl ml s in - let s = ToCodeLow.add_var env pv_res mright rr mr s in + let s = ToCodeLow.add_var env pv_res ml rl ml s in + let s = ToCodeLow.add_var env pv_res mr rr mr s in s in let pre = PVM.subst env spr ef.ef_pr in let post = PVM.subst env spo ef.ef_po in - let concl = f_equivS ml mr pre sl sr post in + let concl = f_equivS mlt mrt {ml;mr;inv=pre} sl sr {ml;mr;inv=post} in FApi.xmutate1 tc `FunToCode [concl] let t_fun_to_code_eager_r tc = let env = FApi.tc1_env tc in let eg = tc1_as_eagerF tc in + let ml, mr = eg.eg_ml, eg.eg_mr in let (fl,fr) = eg.eg_fl, eg.eg_fr in - let ml, sl, rl, al = ToCodeLow.to_code env fl mleft in - let mr, sr, rr, ar = ToCodeLow.to_code env fr mright in + let (ml0, mlt), sl, rl, al = ToCodeLow.to_code env fl ml in + assert (EcIdent.id_equal ml0 ml); + let (mr0, mrt), sr, rr, ar = ToCodeLow.to_code env fr mr in + assert (EcIdent.id_equal mr0 mr); let spr = let s = PVM.empty in - let s = ToCodeLow.add_var_tuple env pv_arg mleft al ml s in - let s = ToCodeLow.add_var_tuple env pv_arg mright ar mr s in + let s = ToCodeLow.add_var_tuple env pv_arg ml0 al ml s in + let s = ToCodeLow.add_var_tuple env pv_arg mr0 ar mr s in s in let spo = let s = PVM.empty in - let s = ToCodeLow.add_var env pv_res mleft rl ml s in - let s = ToCodeLow.add_var env pv_res mright rr mr s in + let s = ToCodeLow.add_var env pv_res ml0 rl ml s in + let s = ToCodeLow.add_var env pv_res mr0 rr mr s in s in let pre = PVM.subst env spr eg.eg_pr in let post = PVM.subst env spo eg.eg_po in let concl = - f_equivS ml mr pre (s_seq eg.eg_sl sl) (s_seq sr eg.eg_sr) post in + f_equivS mlt mrt {ml;mr;inv=pre} (s_seq eg.eg_sl sl) (s_seq sr eg.eg_sr) {ml;mr;inv=post} in FApi.xmutate1 tc `FunToCode [concl] (* -------------------------------------------------------------------- *) @@ -522,8 +533,11 @@ let t_fun_to_code_r tc = let t_fun_to_code = FApi.t_low0 "fun-to-code" t_fun_to_code_r (* -------------------------------------------------------------------- *) -let t_fun_r inv tc = +let t_fun_r (inv: inv) tc = let th tc = + let inv = match inv with + | Inv_ss inv -> inv + | Inv_ts _ -> tc_error !!tc "expected a single sided invariant" in let env = FApi.tc1_env tc in let h = destr_hoareF (FApi.tc1_goal tc) in if NormMp.is_abstract_fun h.hf_f env @@ -531,6 +545,9 @@ let t_fun_r inv tc = else t_hoareF_fun_def tc and teh tc = + let inv = match inv with + | Inv_ss inv -> inv + | Inv_ts _ -> tc_error !!tc "expected a single sided invariant" in let env = FApi.tc1_env tc in let h = destr_eHoareF (FApi.tc1_goal tc) in if NormMp.is_abstract_fun h.ehf_f env @@ -538,6 +555,9 @@ let t_fun_r inv tc = else t_ehoareF_fun_def tc and tbh tc = + let inv = match inv with + | Inv_ss inv -> inv + | Inv_ts _ -> tc_error !!tc "expected a single sided invariant" in let env = FApi.tc1_env tc in let h = destr_bdHoareF (FApi.tc1_goal tc) in if NormMp.is_abstract_fun h.bhf_f env @@ -545,6 +565,9 @@ let t_fun_r inv tc = else t_bdhoareF_fun_def tc and te tc = + let inv = match inv with + | Inv_ts inv -> inv + | Inv_ss _ -> tc_error !!tc "expected a two sided invariant" in let env = FApi.tc1_env tc in let e = destr_equivF (FApi.tc1_goal tc) in if NormMp.is_abstract_fun e.ef_fl env @@ -574,14 +597,16 @@ let process_fun_to_code tc = (* -------------------------------------------------------------------- *) let process_fun_upto_info (bad, p, q) tc = let hyps = FApi.tc1_hyps tc in - let env' = LDecl.inv_memenv hyps in + let ml, mr = EcIdent.create "&1", EcIdent.create "&2" in + let env' = LDecl.inv_memenv ml mr hyps in let p = TTC.pf_process_form !!tc env' tbool p in let q = q |> omap (TTC.pf_process_form !!tc env' tbool) |> odfl f_true in let bad = - let env' = LDecl.push_active (EcMemory.abstract EcFol.mhr) hyps in + let m = EcIdent.create "&bad" in + let env' = LDecl.push_active_ss (EcMemory.abstract m) hyps in TTC.pf_process_form !!tc env' tbool bad in - (bad, p, q) + ({inv=bad;m=mhr}, {inv=p;ml=mleft;mr=mright}, {inv=q;ml=mleft;mr=mright}) (* -------------------------------------------------------------------- *) let process_fun_upto info g = @@ -592,27 +617,31 @@ let process_fun_upto info g = let process_fun_abs inv tc = let t_hoare tc = let hyps = FApi.tc1_hyps tc in - let env' = LDecl.inv_memenv1 hyps in + let m = EcIdent.create "&hr" in + let env' = LDecl.inv_memenv1 m hyps in let inv = TTC.pf_process_form !!tc env' tbool inv in - t_hoareF_abs inv tc + t_hoareF_abs {inv;m} tc and t_ehoare tc = let hyps = FApi.tc1_hyps tc in - let env' = LDecl.inv_memenv1 hyps in + let m = EcIdent.create "&hr" in + let env' = LDecl.inv_memenv1 m hyps in let inv = TTC.pf_process_xreal !!tc env' inv in - t_ehoareF_abs inv tc + t_ehoareF_abs {inv;m} tc and t_bdhoare tc = let hyps = FApi.tc1_hyps tc in - let env' = LDecl.inv_memenv1 hyps in + let m = EcIdent.create "&hr" in + let env' = LDecl.inv_memenv1 m hyps in let inv = TTC.pf_process_form !!tc env' tbool inv in - t_bdhoareF_abs inv tc + t_bdhoareF_abs {inv;m} tc and t_equiv tc = let hyps = FApi.tc1_hyps tc in - let env' = LDecl.inv_memenv hyps in + let ml, mr = EcIdent.create "&1", EcIdent.create "&2" in + let env' = LDecl.inv_memenv ml mr hyps in let inv = TTC.pf_process_form !!tc env' tbool inv in - t_equivF_abs inv tc + t_equivF_abs {inv;ml;mr} tc in t_hF_or_bhF_or_eF ~th:t_hoare ~teh:t_ehoare ~tbh:t_bdhoare ~te:t_equiv tc diff --git a/src/phl/ecPhlFun.mli b/src/phl/ecPhlFun.mli index b33b22f66..1e2f1fee2 100644 --- a/src/phl/ecPhlFun.mli +++ b/src/phl/ecPhlFun.mli @@ -1,11 +1,9 @@ (* -------------------------------------------------------------------- *) -open EcUtils open EcParsetree open EcPath -open EcFol open EcModules -open EcMemory open EcCoreGoal +open EcAst (* -------------------------------------------------------------------- *) (* FIXME: MOVE THIS! *) @@ -21,29 +19,29 @@ type p_upto_info = pformula * pformula * (pformula option) val process_fun_def : FApi.backward val process_fun_abs : pformula -> FApi.backward -val process_fun_upto_info : p_upto_info -> tcenv1 -> form tuple3 +val process_fun_upto_info : p_upto_info -> tcenv1 -> ss_inv * ts_inv * ts_inv val process_fun_upto : p_upto_info -> FApi.backward val process_fun_to_code : FApi.backward (* -------------------------------------------------------------------- *) module FunAbsLow : sig val hoareF_abs_spec : - proofenv -> EcEnv.env -> xpath -> form - -> form * form * form list + proofenv -> EcEnv.env -> xpath -> ss_inv + -> ss_inv * ss_inv * form list val bdhoareF_abs_spec : - proofenv -> EcEnv.env -> xpath -> form - -> form * form * form list + proofenv -> EcEnv.env -> xpath -> ss_inv + -> ss_inv * ss_inv * form list val equivF_abs_spec : - proofenv -> EcEnv.env -> xpath -> xpath -> form - -> form * form * form list + proofenv -> EcEnv.env -> xpath -> xpath -> ts_inv + -> ts_inv * ts_inv * form list end (* -------------------------------------------------------------------- *) -val t_hoareF_abs : form -> FApi.backward -val t_bdhoareF_abs : form -> FApi.backward -val t_equivF_abs : form -> FApi.backward +val t_hoareF_abs : ss_inv -> FApi.backward +val t_bdhoareF_abs : ss_inv -> FApi.backward +val t_equivF_abs : ts_inv -> FApi.backward (* -------------------------------------------------------------------- *) val t_hoareF_fun_def : FApi.backward @@ -51,7 +49,7 @@ val t_bdhoareF_fun_def : FApi.backward val t_equivF_fun_def : FApi.backward (* -------------------------------------------------------------------- *) -val t_equivF_abs_upto : form -> form -> form -> FApi.backward +val t_equivF_abs_upto : ss_inv -> ts_inv -> ts_inv -> FApi.backward (* -------------------------------------------------------------------- *) -val t_fun : form -> FApi.backward +val t_fun : inv -> FApi.backward diff --git a/src/phl/ecPhlHiAuto.ml b/src/phl/ecPhlHiAuto.ml index 083c6e437..c74f27ce3 100644 --- a/src/phl/ecPhlHiAuto.ml +++ b/src/phl/ecPhlHiAuto.ml @@ -57,16 +57,20 @@ and apply_ll_strategy1 (lls : ll_strategy) tc = EcPhlWp.t_wp (Some (Single (Zpr.cpos (-1)))) | LL_RND -> + let m = EcIdent.create "&hr" in EcPhlRnd.t_bdhoare_rnd PNoRndParams - @> EcPhlConseq.t_bdHoareS_conseq f_true f_true + @> EcPhlConseq.t_bdHoareS_conseq {m;inv=f_true} {m;inv=f_true} @~ FApi.t_on1 (-1) ~ttout:ll_trivial t_id | LL_CALL _ -> - EcPhlCall.t_bdhoare_call f_true f_true None + let m = EcIdent.create "&hr" in + EcPhlCall.t_bdhoare_call {m;inv=f_true} {m;inv=f_true} None | LL_JUMP -> + let m = EcIdent.create "&hr" in ( EcPhlApp.t_bdhoare_app - (Zpr.cpos (-1)) (f_true, f_true, f_r1, f_r1, f_r0, f_r1) + (Zpr.cpos (-1)) ({m;inv=f_true}, {m;inv=f_true}, + {m;inv=f_r1}, {m;inv=f_r1}, {m;inv=f_r0}, {m;inv=f_r1}) @~ FApi.t_onalli (function | 1 -> t_id @@ -76,13 +80,14 @@ and apply_ll_strategy1 (lls : ll_strategy) tc = @~ FApi.t_rotate `Left 1 | LL_COND (lls1, lls2) -> + let m = EcIdent.create "&hr" in let condtc = EcPhlCond.t_bdhoare_cond @+ [apply_ll_strategy lls1; apply_ll_strategy lls2] in ( EcPhlApp.t_bdhoare_app - (Zpr.cpos (-1)) (f_true, f_true, f_r1, f_r1, f_r0, f_r1) + (Zpr.cpos (-1)) ({m;inv=f_true}, {m;inv=f_true}, {m;inv=f_r1}, {m;inv=f_r1}, {m;inv=f_r0}, {m;inv=f_r1}) @~ FApi.t_onalli (function | 1 -> t_id @@ -102,7 +107,9 @@ let t_lossless1_r tc = @~ FApi.t_onall (EcLowGoal.t_crush ~delta:true) in let tactic = - (EcPhlConseq.t_bdHoareS_conseq f_true f_true + let m = EcIdent.create "&hr" in + let f_r1: EcAst.ss_inv = {m; inv = f_r1} in + (EcPhlConseq.t_bdHoareS_conseq {m;inv=f_true} {m;inv=f_true} @~ FApi.t_on1 (-1) ~ttout:ll_trivial (EcPhlConseq.t_bdHoareS_conseq_bd FHeq f_r1)) @~ FApi.t_on1 (-1) ~ttout:ll_trivial @@ -133,9 +140,10 @@ let t_lossless tc = | FbdHoareS _ -> t_single tc - | FequivS _hs -> - ((EcPhlApp.t_equiv_app_onesided `Left (EcMatching.Zipper.cpos 0) f_true f_true) @+ - [ (EcPhlApp.t_equiv_app_onesided `Right (EcMatching.Zipper.cpos 0) f_true f_true) @+ + | FequivS hs -> + let ml, mr = fst hs.es_ml, fst hs.es_mr in + ((EcPhlApp.t_equiv_app_onesided `Left (EcMatching.Zipper.cpos 0) {m=ml;inv=f_true} {m=ml;inv=f_true}) @+ + [ (EcPhlApp.t_equiv_app_onesided `Right (EcMatching.Zipper.cpos 0) {m=mr;inv=f_true} {m=mr;inv=f_true}) @+ [ EcPhlSkip.t_skip @! t_trivial ; t_single ]; diff --git a/src/phl/ecPhlHiBdHoare.ml b/src/phl/ecPhlHiBdHoare.ml index c0f438763..19308909f 100644 --- a/src/phl/ecPhlHiBdHoare.ml +++ b/src/phl/ecPhlHiBdHoare.ml @@ -2,7 +2,7 @@ open EcUtils open EcTypes open EcFol -open EcEnv +open EcAst open EcCoreGoal open EcLowGoal @@ -11,16 +11,15 @@ module TTC = EcProofTyping (* -------------------------------------------------------------------- *) let process_bdhoare_split info tc = - let hyps, concl = FApi.tc1_flat tc in + let _, concl = FApi.tc1_flat tc in - let (penv, qenv), pr, po = + let pr, po = match concl.f_node with | FbdHoareS bhs -> - let hyps = LDecl.push_active bhs.bhs_m hyps in - ((hyps, hyps), bhs.bhs_pr, bhs.bhs_po) + (bhs_pr bhs, bhs_po bhs) | FbdHoareF bhf -> - (LDecl.hoareF bhf.bhf_f hyps, bhf.bhf_pr, bhf.bhf_po) + (bhf_pr bhf, bhf_po bhf) | _ -> tc_error !!tc "the conclusion must be a bdhoare judgment" in @@ -28,23 +27,22 @@ let process_bdhoare_split info tc = match info with | EcParsetree.BDH_split_bop (b1, b2, b3) -> let t = - if is_and po then EcPhlBdHoare.t_bdhoare_and - else if is_or po then EcPhlBdHoare.t_bdhoare_or + if is_and po.inv then EcPhlBdHoare.t_bdhoare_and + else if is_or po.inv then EcPhlBdHoare.t_bdhoare_or else tc_error !!tc "the postcondition must be a conjunction or a disjunction" in - - let b1 = TTC.pf_process_form !!tc penv treal b1 in - let b2 = TTC.pf_process_form !!tc penv treal b2 in - let b3 = b3 |> omap (TTC.pf_process_form !!tc penv treal) |> odfl f_r0 in + let _,b1 = TTC.tc1_process_Xhl_form tc treal b1 in + let _,b2 = TTC.tc1_process_Xhl_form tc treal b2 in + let b3 = b3 |> omap (fun f -> snd ( TTC.tc1_process_Xhl_form tc treal f)) |> odfl {m=b1.m;inv=f_r0} in t b1 b2 b3 tc | EcParsetree.BDH_split_or_case (b1, b2, f) -> - let b1 = TTC.pf_process_form !!tc penv treal b1 in - let b2 = TTC.pf_process_form !!tc penv treal b2 in - let f = TTC.pf_process_form !!tc qenv tbool f in + let _, b1 = TTC.tc1_process_Xhl_form tc treal b1 in + let _, b2 = TTC.tc1_process_Xhl_form tc treal b2 in + let _, f = TTC.tc1_process_Xhl_formula tc f in let t_conseq po lemma tactic = let rwtt tc = @@ -58,22 +56,22 @@ let process_bdhoare_split info tc = in FApi.t_seqsub - (EcPhlConseq.t_conseq pr po) + (EcPhlConseq.t_conseq (Inv_ss pr) (Inv_ss po)) [t_true; rwtt; tactic] in t_conseq - (f_or (f_and f po) (f_and (f_not f) po)) + (map_ss_inv2 f_or (map_ss_inv2 f_and f po) (map_ss_inv2 f_and (map_ss_inv1 f_not f) po)) (EcCoreLib.CI_Logic.mk_logic "orDandN") (FApi.t_on1seq 3 - (EcPhlBdHoare.t_bdhoare_or b1 b2 f_r0) + (EcPhlBdHoare.t_bdhoare_or b1 b2 {m=b1.m;inv=f_r0}) (t_conseq - f_false + {inv=f_false;m=mhr} (EcCoreLib.CI_Logic.mk_logic "andDorN") EcHiGoal.process_trivial)) tc | EcParsetree.BDH_split_not (b1, b2) -> - let b1 = b1 |> omap (TTC.pf_process_form !!tc penv treal) |> odfl f_r1 in - let b2 = TTC.pf_process_form !!tc penv treal b2 in - EcPhlBdHoare.t_bdhoare_not b1 b2 tc + let _,b2 = TTC.tc1_process_Xhl_form tc treal b2 in + let b1 = b1 |> omap (fun f -> snd (TTC.tc1_process_Xhl_form tc treal f)) |> odfl {m=b2.m;inv=f_r1} in + EcPhlBdHoare.t_bdhoare_not b1 b2 tc diff --git a/src/phl/ecPhlInline.ml b/src/phl/ecPhlInline.ml index 4e7f6d027..bdf1a7ef6 100644 --- a/src/phl/ecPhlInline.ml +++ b/src/phl/ecPhlInline.ml @@ -169,39 +169,40 @@ end (* -------------------------------------------------------------------- *) let t_inline_hoare_r ~use_tuple sp tc = - let hoare = tc1_as_hoareS tc in - let (me, stmt) = LowInternal.inline ~use_tuple tc hoare.hs_m sp hoare.hs_s in - let concl = f_hoareS_r { hoare with hs_m = me; hs_s = stmt; } in + let hs = tc1_as_hoareS tc in + let (_,mt), stmt = LowInternal.inline ~use_tuple tc hs.hs_m sp hs.hs_s in + let concl = f_hoareS mt (hs_pr hs) stmt (hs_po hs) in FApi.xmutate1 tc `Inline [concl] (* -------------------------------------------------------------------- *) let t_inline_ehoare_r ~use_tuple sp tc = - let hoare = tc1_as_ehoareS tc in - let (me, stmt) = LowInternal.inline ~use_tuple tc hoare.ehs_m sp hoare.ehs_s in - let concl = f_eHoareS_r { hoare with ehs_m = me; ehs_s = stmt; } in + let ehs = tc1_as_ehoareS tc in + let (_,mt), stmt = LowInternal.inline ~use_tuple tc ehs.ehs_m sp ehs.ehs_s in + let concl = f_eHoareS mt (ehs_pr ehs) stmt (ehs_po ehs) in FApi.xmutate1 tc `Inline [concl] (* -------------------------------------------------------------------- *) let t_inline_bdhoare_r ~use_tuple sp tc = - let hoare = tc1_as_bdhoareS tc in - let (me, stmt) = LowInternal.inline ~use_tuple tc hoare.bhs_m sp hoare.bhs_s in - let concl = f_bdHoareS_r { hoare with bhs_m = me; bhs_s = stmt; } in + let bhs = tc1_as_bdhoareS tc in + let (_, mt), stmt = LowInternal.inline ~use_tuple tc bhs.bhs_m sp bhs.bhs_s in + let concl = f_bdHoareS mt (bhs_pr bhs) stmt (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in + FApi.xmutate1 tc `Inline [concl] (* -------------------------------------------------------------------- *) let t_inline_equiv_r ~use_tuple side sp tc = - let equiv = tc1_as_equivS tc in + let es = tc1_as_equivS tc in let concl = match side with | `Left -> - let (me, stmt) = LowInternal.inline ~use_tuple tc equiv.es_ml sp equiv.es_sl in - f_equivS_r { equiv with es_ml = me; es_sl = stmt; } + let ((_,mt), stmt) = LowInternal.inline ~use_tuple tc es.es_ml sp es.es_sl in + f_equivS mt (snd es.es_mr) (es_pr es) stmt es.es_sr (es_po es) | `Right -> - let (me, stmt) = LowInternal.inline ~use_tuple tc equiv.es_mr sp equiv.es_sr in - f_equivS_r { equiv with es_mr = me; es_sr = stmt; } + let ((_,mt), stmt) = LowInternal.inline ~use_tuple tc es.es_mr sp es.es_sr in + f_equivS (snd es.es_ml) mt (es_pr es) es.es_sl stmt (es_po es) in FApi.xmutate1 tc `Inline [concl] diff --git a/src/phl/ecPhlLoopTx.ml b/src/phl/ecPhlLoopTx.ml index 973fe8a14..bef120984 100644 --- a/src/phl/ecPhlLoopTx.ml +++ b/src/phl/ecPhlLoopTx.ml @@ -223,7 +223,7 @@ let process_splitwhile (b, side, cpos) tc = let process_unroll_for side cpos tc = let env = FApi.tc1_env tc in let hyps = FApi.tc1_hyps tc in - let _, c = EcLowPhlGoal.tc1_get_stmt side tc in + let (goal_m, _), c = EcLowPhlGoal.tc1_get_stmt side tc in if not (List.is_empty (fst cpos)) then tc_error !!tc "cannot use deep code position"; @@ -260,19 +260,19 @@ let process_unroll_for side cpos tc = (* Apply loop increment *) let incrz = - let fincr = form_of_expr mhr eincr in + let fincr = ss_inv_of_expr goal_m eincr in fun z0 -> - let f = PVM.subst1 env x mhr (f_int z0) fincr in - match (simplify full_red hyps f).f_node with + let f = map_ss_inv1 (PVM.subst1 env x goal_m (f_int z0)) fincr in + match (simplify full_red hyps f.inv).f_node with | Fint z0 -> z0 | _ -> tc_error !!tc "loop increment does not reduce to a constant" in (* Evaluate loop guard *) let test_cond = - let ftest = form_of_expr mhr t in + let ftest = ss_inv_of_expr goal_m t in fun z0 -> - let cond = PVM.subst1 env x mhr (f_int z0) ftest in - match sform_of_form (simplify full_red hyps cond) with + let cond = map_ss_inv1 (PVM.subst1 env x goal_m (f_int z0)) ftest in + match sform_of_form (simplify full_red hyps cond.inv) with | SFtrue -> true | SFfalse -> false | _ -> tc_error !!tc "while loop condition does not reduce to a constant" in @@ -284,7 +284,7 @@ let process_unroll_for side cpos tc = let zs = eval_cond z0 in let hds = Array.make (List.length zs) None in let m = LDecl.fresh_id hyps "&m" in - let x = f_pvar x tint mhr in + let x = f_pvar x tint goal_m in let t_set i pos z tc = hds.(i) <- Some (FApi.tc1_handle tc, pos, z); t_id tc in @@ -299,25 +299,28 @@ let process_unroll_for side cpos tc = | z :: zs -> ((t_rcond side (zs <> []) (Zpr.cpos pos)) @+ [FApi.t_try (t_intro_i m) @! - t_conseq (f_eq x (f_int z)) @! + t_conseq (Inv_ss (map_ss_inv1 (fun x -> f_eq x (f_int z)) x)) @! t_set i pos z; t_doit (i+1) (pos + blen) zs]) tc in let t_conseq_nm tc = - (EcPhlConseq.t_hoareS_conseq_nm (tc1_get_pre tc) f_true @+ - [ t_trivial; t_trivial; EcPhlTAuto.t_hoare_true]) tc in + match (tc1_get_pre tc) with + | Inv_ss inv -> + (EcPhlConseq.t_hoareS_conseq_nm inv {m=inv.m;inv=f_true} @+ + [ t_trivial; t_trivial; EcPhlTAuto.t_hoare_true]) tc + | _ -> tc_error !!tc "expecting single sided precondition" in let doi i tc = if Array.length hds <= i then t_id tc else let (_h,pos,_z) = oget hds.(i) in if i = 0 then (EcPhlWp.t_wp (Some (Single (Zpr.cpos (pos - 2)))) @! - t_conseq f_true @! EcPhlTAuto.t_hoare_true) tc + t_conseq (Inv_ss {inv=f_true;m=x.m}) @! EcPhlTAuto.t_hoare_true) tc else let (h', pos', z') = oget hds.(i-1) in FApi.t_seqs [ EcPhlWp.t_wp (Some (Single (Zpr.cpos (pos-2)))); - EcPhlApp.t_hoare_app (Zpr.cpos (pos' - 1)) (f_eq x (f_int z')) @+ + EcPhlApp.t_hoare_app (Zpr.cpos (pos' - 1)) (map_ss_inv2 f_eq x {m=goal_m;inv=f_int z'}) @+ [t_apply_hd h'; t_conseq_nm] ] tc in diff --git a/src/phl/ecPhlPr.ml b/src/phl/ecPhlPr.ml index 25f1f3b31..4fa1ae85c 100644 --- a/src/phl/ecPhlPr.ml +++ b/src/phl/ecPhlPr.ml @@ -6,6 +6,7 @@ open EcEnv open EcAst open EcCoreGoal open EcLowPhlGoal +open EcSubst module TTC = EcProofTyping @@ -22,20 +23,21 @@ let t_bdhoare_ppr_r tc = let bhf = tc1_as_bdhoareF tc in let f_xpath = bhf.bhf_f in let fun_ = EcEnv.Fun.by_xpath f_xpath env in - let penv,_qenv = EcEnv.Fun.hoareF_memenv f_xpath env in - let m = EcIdent.create "&m" in - let args = to_args fun_ (f_pvarg fun_.f_sig.fs_arg m) in - (* Warning: currently no substitution on pre,post since penv is always mhr *) - let pre,post = bhf.bhf_pr, bhf.bhf_po in + let penv,_qenv = EcEnv.Fun.hoareF_memenv bhf.bhf_m f_xpath env in + let m = EcIdent.create "&hr" in + let args = map_ss_inv1 (to_args fun_) (f_pvarg fun_.f_sig.fs_arg m) in + let pre,post = (bhf_pr bhf), (bhf_po bhf) in let fop = match bhf.bhf_cmp with | FHle -> f_real_le | FHge -> fun x y -> f_real_le y x | FHeq -> f_eq in - let subst = Fsubst.f_subst_mem (fst penv) m in - let concl = fop (f_pr m f_xpath args post) (subst bhf.bhf_bd) in - let concl = f_imp (subst pre) concl in - let concl = f_forall_mems [m,snd penv] concl in + let bd = ss_inv_rebind (bhf_bd bhf) m in + let concl = map_ss_inv2 fop (map_ss_inv1 (fun args -> f_pr m f_xpath args post) args) + bd in + let pre = ss_inv_rebind pre m in + let concl = map_ss_inv2 f_imp pre concl in + let concl = EcSubst.f_forall_mems_ss_inv (m,snd penv) concl in FApi.xmutate1 tc `PPR [concl] (* -------------------------------------------------------------------- *) @@ -50,25 +52,22 @@ let t_equiv_ppr_r ty phi_l phi_r tc = let (fl, fr) = (ef.ef_fl, ef.ef_fr) in let funl = EcEnv.Fun.by_xpath fl env in let funr = EcEnv.Fun.by_xpath fr env in - let (penvl,penvr), (qenvl,qenvr) = EcEnv.Fun.equivF_memenv fl fr env in - let argsl = to_args funl (f_pvarg funl.f_sig.fs_arg (fst penvl)) in - let argsr = to_args funr (f_pvarg funr.f_sig.fs_arg (fst penvr)) in + let (penvl,penvr), (qenvl,qenvr) = EcEnv.Fun.equivF_memenv ef.ef_ml ef.ef_mr fl fr env in + let argsl = map_ss_inv1 (to_args funl) (f_pvarg funl.f_sig.fs_arg (fst penvl)) in + let argsr = map_ss_inv1 (to_args funr) (f_pvarg funr.f_sig.fs_arg (fst penvr)) in let a_id = EcIdent.create "a" in let a_f = f_local a_id ty in - let smem1 = Fsubst.f_bind_mem Fsubst.f_subst_id mleft mhr in - let smem2 = Fsubst.f_bind_mem Fsubst.f_subst_id mright mhr in - let phi1 = Fsubst.f_subst smem1 phi_l in - let phi2 = Fsubst.f_subst smem2 phi_r in - let pr1 = f_pr (fst penvl) fl argsl (f_eq phi1 a_f) in - let pr2 = f_pr (fst penvr) fr argsr (f_eq phi2 a_f) in + let pr1 = f_pr (fst penvl) fl argsl.inv (map_ss_inv1 (fun p -> f_eq p a_f) phi_l) in + let pr2 = f_pr (fst penvr) fr argsr.inv (map_ss_inv1 (fun p -> f_eq p a_f) phi_r) in let concl_pr = - f_forall_mems [penvl; penvr] - (f_forall_simpl [a_id,GTty ty] - (f_imp_simpl ef.ef_pr (f_eq_simpl pr1 pr2))) in - let concl_po = - f_forall_mems [qenvl; qenvr] + f_forall_mems_ts_inv penvl penvr + (map_ts_inv1 (f_forall_simpl [a_id,GTty ty]) + (map_ts_inv1 (fun pr -> f_imp_simpl pr (f_eq_simpl pr1 pr2)) (ef_pr ef))) in + let phi_l = ss_inv_generalize_as_left phi_l ef.ef_ml ef.ef_mr in + let phi_r = ss_inv_generalize_as_right phi_r ef.ef_ml ef.ef_mr in + let concl_po = f_forall_mems_ts_inv qenvl qenvr (map_ts_inv3 (fun phi_l phi_r po -> (f_forall_simpl [a_id, GTty ty] - (f_imps_simpl [f_eq phi_l a_f;f_eq phi_r a_f] ef.ef_po)) in + (f_imps_simpl [f_eq phi_l a_f;f_eq phi_r a_f] po))) phi_l phi_r (ef_po ef)) in FApi.xmutate1 tc `PPR [concl_po; concl_pr] (* -------------------------------------------------------------------- *) @@ -85,12 +84,14 @@ let process_ppr info tc = | Some (phi1, phi2) -> let hyps = FApi.tc1_hyps tc in let ef = tc1_as_equivF tc in - let qenv = snd (LDecl.equivF ef.ef_fl ef.ef_fr hyps) in - let phi1 = TTC.pf_process_form_opt !!tc qenv None phi1 in - let phi2 = TTC.pf_process_form_opt !!tc qenv None phi2 in - if not (EcReduction.EqTest.for_type (LDecl.toenv qenv) phi1.f_ty phi2.f_ty) then + let qenvl = snd (LDecl.hoareF ef.ef_ml ef.ef_fl hyps) in + let qenvr = snd (LDecl.hoareF ef.ef_mr ef.ef_fr hyps) in + (* TODO: These should be one-sided *) + let phi1 = TTC.pf_process_form_opt !!tc qenvl None phi1 in + let phi2 = TTC.pf_process_form_opt !!tc qenvr None phi2 in + if not (EcReduction.EqTest.for_type (LDecl.toenv hyps) phi1.f_ty phi2.f_ty) then tc_error !!tc "formulas must have convertible types"; - t_equiv_ppr phi1.f_ty phi1 phi2 tc + t_equiv_ppr phi1.f_ty {m=ef.ef_ml;inv=phi1} {m=ef.ef_mr;inv=phi2} tc (* -------------------------------------------------------------------- *) let t_prbounded_r conseq tc = @@ -99,7 +100,7 @@ let t_prbounded_r conseq tc = let (m, pr, po, cmp, bd) = match concl.f_node with | FbdHoareF hf -> - let m = fst (Fun.hoareF_memenv hf.bhf_f env) in + let m = fst (Fun.hoareF_memenv hf.bhf_m hf.bhf_f env) in (m, hf.bhf_pr, hf.bhf_po, hf.bhf_cmp, hf.bhf_bd) | FbdHoareS hf -> @@ -147,9 +148,9 @@ let t_prfalse tc = (* the event is false *) let smem = Fsubst.f_bind_mem Fsubst.f_subst_id mhr mhr in - let ev = Fsubst.f_subst smem ev in + let ev' = Fsubst.f_subst smem ev.inv in let fun_ = EcEnv.Fun.by_xpath f env in - let me = EcEnv.Fun.actmem_post mhr fun_ in - let concl_po = f_forall_mems [me] (f_imp f_false ev) in + let me = EcEnv.Fun.actmem_post ev.m fun_ in + let concl_po = f_forall_mems [me] (f_imp f_false ev') in FApi.xmutate1 tc `PrFalse [is_zero; concl_po] diff --git a/src/phl/ecPhlPr.mli b/src/phl/ecPhlPr.mli index 82f15ef2b..69b24e7f0 100644 --- a/src/phl/ecPhlPr.mli +++ b/src/phl/ecPhlPr.mli @@ -1,14 +1,13 @@ (* -------------------------------------------------------------------- *) open EcUtils open EcParsetree -open EcTypes -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) val t_hoare_ppr : backward val t_bdhoare_ppr : backward -val t_equiv_ppr : ty -> form -> form -> backward +val t_equiv_ppr : ty -> ss_inv -> ss_inv -> backward (* -------------------------------------------------------------------- *) val t_prbounded : bool -> backward diff --git a/src/phl/ecPhlPrRw.ml b/src/phl/ecPhlPrRw.ml index 0a7be9d6f..bac3d6892 100644 --- a/src/phl/ecPhlPrRw.ml +++ b/src/phl/ecPhlPrRw.ml @@ -16,66 +16,73 @@ let t_pr_lemma lemma tc = FApi.xmutate1 tc `RwPr [] (* -------------------------------------------------------------------- *) -let pr_eq env m f args p1 p2 = - let mem = Fun.prF_memenv mhr f env in - let hyp = f_forall_mems [ mem ] (f_iff p1 p2) in - let concl = f_eq (f_pr m f args p1) (f_pr m f args p2) in +let pr_eq env pr_m f args p1 p2 = + let m = p1.m in + let mem = Fun.prF_memenv m f env in + let hyp = EcSubst.f_forall_mems_ss_inv mem (map_ss_inv2 f_iff p1 p2) in + let concl = f_eq (f_pr pr_m f args p1) (f_pr pr_m f args p2) in f_imp hyp (f_eq concl f_true) -let pr_sub env m f args p1 p2 = - let mem = Fun.prF_memenv mhr f env in - let hyp = f_forall_mems [ mem ] (f_imp p1 p2) in - let concl = f_real_le (f_pr m f args p1) (f_pr m f args p2) in +let pr_sub env pr_m f args p1 p2 = + let m = p1.m in + let mem = Fun.prF_memenv m f env in + let hyp = EcSubst.f_forall_mems_ss_inv mem (map_ss_inv2 f_imp p1 p2) in + let concl = f_real_le (f_pr pr_m f args p1) (f_pr pr_m f args p2) in f_imp hyp (f_eq concl f_true) -let pr_false m f args = f_eq (f_pr m f args f_false) f_r0 +let pr_false pr_m f args = + let m = EcIdent.create "&hr" in + f_eq (f_pr pr_m f args {m;inv=f_false}) f_r0 -let pr_not m f args p = +let pr_not pr_m f args p = + let m = p.m in f_eq - (f_pr m f args (f_not p)) - (f_real_sub (f_pr m f args f_true) (f_pr m f args p)) + (f_pr pr_m f args (map_ss_inv1 f_not p)) + (f_real_sub (f_pr pr_m f args {m;inv=f_true}) (f_pr pr_m f args p)) -let pr_or m f args por p1 p2 = - let pr1 = f_pr m f args p1 in - let pr2 = f_pr m f args p2 in - let pr12 = f_pr m f args (f_and p1 p2) in +let pr_or pr_m f args por p1 p2 = + let pr1 = f_pr pr_m f args p1 in + let pr2 = f_pr pr_m f args p2 in + let pr12 = f_pr pr_m f args (map_ss_inv2 f_and p1 p2) in let pr = f_real_sub (f_real_add pr1 pr2) pr12 in - f_eq (f_pr m f args (por p1 p2)) pr - -let pr_disjoint env m f args por p1 p2 = - let mem = Fun.prF_memenv mhr f env in - let hyp = f_forall_mems [ mem ] (f_not (f_and p1 p2)) in - let pr1 = f_pr m f args p1 in - let pr2 = f_pr m f args p2 in + f_eq (f_pr pr_m f args (por p1 p2)) pr + +let pr_disjoint env pr_m f args por p1 p2 = + let m = p1.m in + let mem = Fun.prF_memenv m f env in + let hyp = EcSubst.f_forall_mems_ss_inv mem (map_ss_inv1 f_not (map_ss_inv2 f_and p1 p2)) in + let pr1 = f_pr pr_m f args p1 in + let pr2 = f_pr pr_m f args p2 in let pr = f_real_add pr1 pr2 in - f_imp hyp (f_eq (f_pr m f args (por p1 p2)) pr) + f_imp hyp (f_eq (f_pr pr_m f args (por p1 p2)) pr) -let pr_split m f args ev1 ev2 = - let pr = f_pr m f args ev1 in - let pr1 = f_pr m f args (f_and ev1 ev2) in - let pr2 = f_pr m f args (f_and ev1 (f_not ev2)) in +let pr_split pr_m f args ev1 ev2 = + let pr = f_pr pr_m f args ev1 in + let pr1 = f_pr pr_m f args (map_ss_inv2 f_and ev1 ev2) in + let pr2 = f_pr pr_m f args (map_ss_inv2 f_and ev1 (map_ss_inv1 f_not ev2)) in f_eq pr (f_real_add pr1 pr2) -let pr_ge0 m f args ev = - let pr = f_pr m f args ev in +let pr_ge0 pr_m f args ev = + let pr = f_pr pr_m f args ev in f_eq (f_real_le f_r0 pr) f_true -let pr_le1 m f args ev = - let pr = f_pr m f args ev in +let pr_le1 pr_m f args ev = + let pr = f_pr pr_m f args ev in f_eq (f_real_le pr f_r1) f_true let pr_sum env pr = let prf = EcEnv.Fun.by_xpath pr.pr_fun env in let xty = prf.f_sig.fs_ret in let x = EcIdent.create "x" in - let fx = f_local x xty in - + let ev = pr.pr_event in + let m = ev.m in + let fx = {m;inv=f_local x xty} in let prx = let event = - f_and_simpl pr.pr_event (f_eq (f_pvar EcTypes.pv_res xty EcFol.mhr) fx) - in - f_pr pr.pr_mem pr.pr_fun pr.pr_args event - in + map_ss_inv2 f_and_simpl + ev + (map_ss_inv2 f_eq (f_pvar EcTypes.pv_res xty ev.m) fx) + in f_pr pr.pr_mem pr.pr_fun pr.pr_args event in let prx = EcFol.f_app @@ -87,13 +94,14 @@ let pr_sum env pr = f_eq (f_pr_r pr) prx -let pr_mu1_le_eq_mu1 m f args resv k fresh_id d = +let pr_mu1_le_eq_mu1 pr_m f args resv k fresh_id d = + let m = resv.m in let kfresh = f_local fresh_id k.f_ty in - let f_ll = f_bdHoareF f_true f f_true FHeq f_r1 + let f_ll = f_bdHoareF {m;inv=f_true} f {m;inv=f_true} FHeq {m;inv=f_r1} and f_le_mu1 = f_forall [ (fresh_id, gtty k.f_ty) ] - (f_real_le (f_pr m f args (f_eq resv kfresh)) (f_mu_x d kfresh)) + (f_real_le (f_pr pr_m f args {m;inv=f_eq resv.inv kfresh}) (f_mu_x d kfresh)) and concl = - f_eq (f_pr m f args (f_eq resv k)) (f_mu_x d k) in + f_eq (f_pr pr_m f args {m;inv=f_eq resv.inv k}) (f_mu_x d k) in f_imp f_ll (f_imp f_le_mu1 concl) (* -------------------------------------------------------------------- *) @@ -102,7 +110,7 @@ exception FoundPr of form let select_pr on_ev sid f = match f.f_node with | Fpr { pr_event = ev } -> - if on_ev ev && Mid.set_disjoint f.f_fv sid then raise (FoundPr f) + if on_ev ev.inv && Mid.set_disjoint f.f_fv sid then raise (FoundPr f) else false | _ -> false @@ -157,7 +165,7 @@ let pr_rewrite_lemma = ] (* -------------------------------------------------------------------- *) -let t_pr_rewrite_low (s, dof) tc = +let t_pr_rewrite_low (s, (dof: (_ -> _ -> _ -> ss_inv) option)) tc = let kind = try List.assoc s pr_rewrite_lemma with Not_found -> @@ -194,18 +202,22 @@ let t_pr_rewrite_low (s, dof) tc = let lemma, args = match kind with | `Mu1LeEqMu1 -> - let { pr_mem; pr_fun; pr_args; pr_event } = destr_pr torw in - let (resv, k) = destr_eq pr_event in + let { pr_fun; pr_args; pr_mem } as pr = destr_pr torw in + let (resv, k) = map_ss_inv_destr2 destr_eq pr.pr_event in let k_id = EcEnv.LDecl.fresh_id hyps "k" in - let d = (oget dof) tc torw (EcTypes.tdistr k.f_ty) in - (pr_mu1_le_eq_mu1 pr_mem pr_fun pr_args resv k k_id d, 2) + let d = (oget dof) tc torw (EcTypes.tdistr k.inv.f_ty) in + (* FIXME: Ensure that d.inv does not use d.m *) + (* FIXME: Ensure that k.inv does not use k.m *) + (pr_mu1_le_eq_mu1 pr_mem pr_fun pr_args resv k.inv k_id d.inv, 2) | (`MuEq | `MuSub as kind) -> begin match torw.f_node with - | Fapp(_, [{f_node = Fpr ({ pr_event = ev1 } as pr) }; - {f_node = Fpr ({ pr_event = ev2 }) };]) + | Fapp(_, [{f_node = Fpr pr1 }; + {f_node = Fpr pr2 };]) -> begin - let { pr_mem = m; pr_fun = f; pr_args = args } = pr in + let { pr_mem = m ; pr_fun = f; pr_args = args } = pr1 in + let ev1 = pr1.pr_event in + let ev2 = EcSubst.ss_inv_rebind pr2.pr_event ev1.m in match kind with | `MuEq -> (pr_eq env m f args ev1 ev2, 1) | `MuSub -> (pr_sub env m f args ev1 ev2, 1) @@ -219,37 +231,39 @@ let t_pr_rewrite_low (s, dof) tc = | `MuNot -> let { pr_mem = m ; pr_fun = f; pr_args = args; } as pr = destr_pr torw in - let ev = destr_not pr.pr_event in + let ev = map_ss_inv1 destr_not pr.pr_event in (pr_not m f args ev, 0) | `MuOr -> let { pr_mem = m ; pr_fun = f; pr_args = args; } as pr = destr_pr torw in - let (asym, (ev1, ev2)) = destr_or_r pr.pr_event in - (pr_or m f args (match asym with | `Asym -> f_ora | `Sym -> f_or) ev1 ev2, 0) + let asym = fst (destr_or_r pr.pr_event.inv) in + let (ev1, ev2) = map_ss_inv_destr2 (fun prev -> snd (destr_or_r prev)) pr.pr_event in + (pr_or m f args (match asym with | `Asym -> map_ss_inv2 f_ora | `Sym -> map_ss_inv2 f_or) ev1 ev2, 0) | `MuDisj -> let { pr_mem = m ; pr_fun = f; pr_args = args; } as pr = destr_pr torw in - let (asym, (ev1, ev2)) = destr_or_r pr.pr_event in - (pr_disjoint env m f args (match asym with | `Asym -> f_ora | `Sym -> f_or) ev1 ev2, 1) + let asym = fst (destr_or_r pr.pr_event.inv) in + let (ev1, ev2) = map_ss_inv_destr2 (fun prev -> snd (destr_or_r prev)) pr.pr_event in + (pr_disjoint env m f args (match asym with | `Asym -> map_ss_inv2 f_ora | `Sym -> map_ss_inv2 f_or) ev1 ev2, 1) | `MuSplit -> let pr = destr_pr torw in - let ev' = (oget dof) tc torw EcTypes.tbool in + let ev' = EcSubst.ss_inv_rebind ((oget dof) tc torw EcTypes.tbool) pr.pr_event.m in (pr_split pr.pr_mem pr.pr_fun pr.pr_args pr.pr_event ev', 0) | `MuGe0 -> begin match torw.f_node with | Fapp({f_node = Fop _}, [_; {f_node = Fpr pr}]) -> - let { pr_mem = m; pr_fun = f; pr_args = args; pr_event = ev } = pr in - (pr_ge0 m f args ev, 0) + let { pr_mem = m; pr_fun = f; pr_args = args } = pr in + (pr_ge0 m f args pr.pr_event, 0) | _ -> assert false end | `MuLe1 -> begin match torw.f_node with | Fapp({f_node = Fop _}, [{f_node = Fpr pr}; _]) -> - let { pr_mem = m; pr_fun = f; pr_args = args; pr_event = ev } = pr in - (pr_le1 m f args ev, 0) + let { pr_mem = m; pr_fun = f; pr_args = args } = pr in + (pr_le1 m f args pr.pr_event, 0) | _ -> assert false end @@ -272,8 +286,9 @@ let t_pr_rewrite (s, f) tc = let to_env f tc torw ty = let env, hyps, _ = FApi.tc1_eflat tc in let pr = destr_pr torw in - let mp = EcEnv.Fun.prF_memenv EcFol.mhr pr.pr_fun env in - let hyps = LDecl.push_active mp hyps in - EcProofTyping.process_form hyps f ty + let m = EcIdent.create "&hr" in + let mp = EcEnv.Fun.prF_memenv m pr.pr_fun env in + let hyps = LDecl.push_active_ss mp hyps in + {m;inv=EcProofTyping.process_form hyps f ty} in t_pr_rewrite_low (s, omap to_env f) tc diff --git a/src/phl/ecPhlPrRw.mli b/src/phl/ecPhlPrRw.mli index 64a50ad4c..6fb9ee259 100644 --- a/src/phl/ecPhlPrRw.mli +++ b/src/phl/ecPhlPrRw.mli @@ -1,8 +1,9 @@ (* -------------------------------------------------------------------- *) open EcSymbols open EcCoreGoal +open EcAst (* -------------------------------------------------------------------- *) -val t_pr_rewrite_i : symbol * EcFol.form option -> FApi.backward +val t_pr_rewrite_i : symbol * ss_inv option -> FApi.backward val t_pr_rewrite : symbol * EcParsetree.pformula option -> FApi.backward diff --git a/src/phl/ecPhlRCond.ml b/src/phl/ecPhlRCond.ml index e28a07939..7baa2dc2c 100644 --- a/src/phl/ecPhlRCond.ml +++ b/src/phl/ecPhlRCond.ml @@ -6,6 +6,8 @@ open EcTypes open EcDecl open EcModules open EcFol +open EcParsetree +open EcSubst open EcCoreGoal open EcLowPhlGoal @@ -24,8 +26,8 @@ module Low = struct Format.fprintf fmt "the targetted instruction is not a conditionnal") in - let f_e = form_of_expr m e in - let f_e = if b then f_e else f_not f_e in + let f_e = ss_inv_of_expr m e in + let f_e = if b then f_e else map_ss_inv1 f_not f_e in (stmt head, e, f_e, stmt (head @ s @ tail)) @@ -35,8 +37,8 @@ module Low = struct let hs = tc1_as_hoareS tc in let m = EcMemory.memory hs.hs_m in let hd,_,e,s = gen_rcond (!!tc, env) b m at_pos hs.hs_s in - let concl1 = f_hoareS_r { hs with hs_s = hd; hs_po = e } in - let concl2 = f_hoareS_r { hs with hs_s = s } in + let concl1 = f_hoareS (snd hs.hs_m) (hs_pr hs) hd e in + let concl2 = f_hoareS (snd hs.hs_m) (hs_pr hs) s (hs_po hs) in FApi.xmutate1 tc `RCond [concl1; concl2] (* ------------------------------------------------------------------ *) @@ -45,13 +47,14 @@ module Low = struct let hs = tc1_as_ehoareS tc in let m = EcMemory.memory hs.ehs_m in let hd,_,e,s = gen_rcond (!!tc, env) b m at_pos hs.ehs_s in - let pre = - match destr_app hs.ehs_pr with + let pre pr = + match destr_app pr with | o, pre :: _ when f_equal o fop_interp_ehoare_form -> pre | _ -> tc_error !!tc "the pre should have the form \"_ `|` _\"" in + let pre = map_ss_inv1 pre (ehs_pr hs) in - let concl1 = f_hoareS hs.ehs_m pre hd e in - let concl2 = f_eHoareS_r { hs with ehs_s = s } in + let concl1 = f_hoareS (snd hs.ehs_m) pre hd e in + let concl2 = f_eHoareS (snd hs.ehs_m) (ehs_pr hs) s (ehs_po hs) in FApi.xmutate1 tc `RCond [concl1; concl2] (* ------------------------------------------------------------------ *) @@ -60,8 +63,8 @@ module Low = struct let bhs = tc1_as_bdhoareS tc in let m = EcMemory.memory bhs.bhs_m in let hd,_,e,s = gen_rcond (!!tc, env) b m at_pos bhs.bhs_s in - let concl1 = f_hoareS bhs.bhs_m bhs.bhs_pr hd e in - let concl2 = f_bdHoareS_r { bhs with bhs_s = s } in + let concl1 = f_hoareS (snd bhs.bhs_m) (bhs_pr bhs) hd e in + let concl2 = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `RCond [concl1; concl2] (* ------------------------------------------------------------------ *) @@ -72,17 +75,16 @@ module Low = struct match side with | `Left -> es.es_ml,es.es_mr, es.es_sl | `Right -> es.es_mr,es.es_ml, es.es_sr in - let hd,_,e,s = gen_rcond (!!tc, env) b EcFol.mhr at_pos s in - let mo' = EcIdent.create "&m" in - let s1 = Fsubst.f_subst_id in - let s1 = Fsubst.f_bind_mem s1 (EcMemory.memory m) EcFol.mhr in - let s1 = Fsubst.f_bind_mem s1 (EcMemory.memory mo) mo' in - let pre1 = Fsubst.f_subst s1 es.es_pr in - let concl1 = - f_forall_mems [mo', EcMemory.memtype mo] - (f_hoareS (EcFol.mhr, EcMemory.memtype m) pre1 hd e) in + let ts_inv_lower_side2 = sideif side ts_inv_lower_left2 ts_inv_lower_right2 in + let ss_inv_generalize_other = sideif side ss_inv_generalize_right ss_inv_generalize_left in + let hd,_,e,s = gen_rcond (!!tc, env) b (fst m) at_pos s in + let e = ss_inv_generalize_other e (fst mo) in + let concl1 = + EcSubst.f_forall_mems_ss_inv mo + (ts_inv_lower_side2 (fun pr po -> + f_hoareS (snd m) pr hd po) (es_pr es) e) in let sl,sr = match side with `Left -> s, es.es_sr | `Right -> es.es_sl, s in - let concl2 = f_equivS_r { es with es_sl = sl; es_sr = sr } in + let concl2 = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl sr (es_po es) in FApi.xmutate1 tc `RCond [concl1; concl2] (* ------------------------------------------------------------------ *) @@ -143,7 +145,7 @@ module LowMatch = struct "the targetted instruction is not a match") in - let f = form_of_expr m e in + let f = ss_inv_of_expr m e in ((stmt head, subs, tail), (e, f), infos, cvars) @@ -161,10 +163,10 @@ module LowMatch = struct else EcIdent.fresh x in (x, xty)) cvars in let vars = List.map (curry f_local) names in - let cty = toarrow (List.snd names) f.f_ty in + let cty = toarrow (List.snd names) f.inv.f_ty in let po = f_op cname (List.snd tyinst) cty in - let po = f_app po vars f.f_ty in - f_exists (List.map (snd_map gtty) names) (f_eq f po) in + let po = f_app po vars f.inv.f_ty in + map_ss_inv1 (f_exists (List.map (snd_map gtty) names)) (map_ss_inv2 f_eq f {m;inv=po}) in let me, pvs = let cvars = @@ -191,9 +193,9 @@ module LowMatch = struct let epr, asgn = if frame then begin let vars = List.map (fun (pv, ty) -> f_pvar pv ty (fst me)) pvs in - let epr = f_op cname (List.snd tyinst) f.f_ty in - let epr = f_app epr vars f.f_ty in - Some (f_eq f epr), [] + let epr = f_op cname (List.snd tyinst) f.inv.f_ty in + let epr = map_ss_inv (fun vars -> f_app epr vars f.inv.f_ty) vars in + Some (map_ss_inv2 f_eq f epr), [] end else begin let asgn = EcModules.lv_of_list pvs |> omap (fun lv -> @@ -215,10 +217,10 @@ module LowMatch = struct let (epr, hd, po1), (me, full) = gen_rcond_full (!!tc, FApi.tc1_env tc) c hs.hs_m at_pos hs.hs_s in - let pr = ofold f_and hs.hs_pr epr in + let pr = ofold (map_ss_inv2 f_and) (hs_pr hs) epr in - let concl1 = f_hoareS_r { hs with hs_s = hd; hs_po = po1; } in - let concl2 = f_hoareS_r { hs with hs_pr = pr; hs_m = me; hs_s = full; } in + let concl1 = f_hoareS (snd hs.hs_m) (hs_pr hs) hd po1 in + let concl2 = f_hoareS (snd me) pr full (hs_po hs) in FApi.xmutate1 tc `RCondMatch [concl1; concl2] @@ -228,10 +230,10 @@ module LowMatch = struct let (epr, hd, po1), (me, full) = gen_rcond_full (!!tc, FApi.tc1_env tc) c hs.ehs_m at_pos hs.ehs_s in - let pr = ofold f_and hs.ehs_pr epr in + let pr = ofold (map_ss_inv2 f_and) (ehs_pr hs) epr in - let concl1 = f_eHoareS_r { hs with ehs_s = hd; ehs_po = po1; } in - let concl2 = f_eHoareS_r { hs with ehs_pr = pr; ehs_m = me; ehs_s = full; } in + let concl1 = f_eHoareS (snd hs.ehs_m) (ehs_pr hs) hd po1 in + let concl2 = f_eHoareS (snd me) pr full (ehs_po hs) in FApi.xmutate1 tc `RCondMatch [concl1; concl2] @@ -241,16 +243,17 @@ module LowMatch = struct let (epr, hd, po1), (me, full) = gen_rcond_full (!!tc, FApi.tc1_env tc) c bhs.bhs_m at_pos bhs.bhs_s in - let pr = ofold f_and bhs.bhs_pr epr in + let pr = ofold (map_ss_inv2 f_and) (bhs_pr bhs) epr in - let concl1 = f_hoareS bhs.bhs_m bhs.bhs_pr hd po1 in - let concl2 = f_bdHoareS_r { bhs with bhs_pr = pr; bhs_m = me; bhs_s = full; } in + let concl1 = f_hoareS (snd bhs.bhs_m) (bhs_pr bhs) hd po1 in + let concl2 = f_bdHoareS (snd me) pr full (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `RCondMatch [concl1; concl2] (* ------------------------------------------------------------------ *) let t_equiv_rcond_match_r side c at_pos tc = let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in let m, mo, s = match side with @@ -258,22 +261,20 @@ module LowMatch = struct | `Right -> es.es_mr, es.es_ml, es.es_sr in let (epr, hd, po1), (me, full) = - gen_rcond_full (!!tc, FApi.tc1_env tc) c (EcFol.mhr, snd m) at_pos s in + gen_rcond_full (!!tc, FApi.tc1_env tc) c m at_pos s in - let mo' = EcIdent.create "&m" in - let s1 = Fsubst.f_subst_id in - let s1 = Fsubst.f_bind_mem s1 (EcMemory.memory m) EcFol.mhr in - let s1 = Fsubst.f_bind_mem s1 (EcMemory.memory mo) mo' in - let pre1 = Fsubst.f_subst s1 es.es_pr in + let ss_inv_generalize_other inv = sideif side + (ss_inv_generalize_right inv mr) (ss_inv_generalize_left inv ml) in let epr = omap (fun epr -> - let se = Fsubst.f_subst_id in - let se = Fsubst.f_bind_mem se EcFol.mhr (EcMemory.memory m) in - Fsubst.f_subst se epr) epr in + ss_inv_generalize_other (ss_inv_rebind epr (fst m))) epr in + + let ts_inv_lower_side1 = + sideif side ts_inv_lower_left1 ts_inv_lower_right1 in let concl1 = - f_forall_mems [mo', EcMemory.memtype mo] - (f_hoareS (EcFol.mhr, EcMemory.memtype m) pre1 hd po1) in + f_forall_mems_ss_inv mo + (ts_inv_lower_side1 (fun pr -> f_hoareS (snd m) pr hd po1) (es_pr es)) in let (ml, mr), (sl, sr) = match side with @@ -286,9 +287,7 @@ module LowMatch = struct (es.es_sl, full) in let concl2 = - f_equivS_r { es with - es_pr = ofold f_and es.es_pr epr; - es_ml = ml; es_mr = mr; es_sl = sl; es_sr = sr } in + f_equivS (snd ml) (snd mr) (ofold (map_ts_inv2 f_and) (es_pr es) epr) sl sr (es_po es) in FApi.xmutate1 tc `RCond [concl1; concl2] (* ------------------------------------------------------------------ *) diff --git a/src/phl/ecPhlRewrite.ml b/src/phl/ecPhlRewrite.ml index 19fce1431..d25483353 100644 --- a/src/phl/ecPhlRewrite.ml +++ b/src/phl/ecPhlRewrite.ml @@ -27,10 +27,10 @@ let t_change let data, e' = expr e (hyps, m) in let mid = EcMemory.memory m in - let f = form_of_expr mid e in - let f' = form_of_expr mid e' in + let f = ss_inv_of_expr mid e in + let f' = ss_inv_of_expr mid e' in - (data, [f_forall_mems [m] (f_eq f f')]), [mk e'] + (data, [EcSubst.f_forall_mems_ss_inv m (map_ss_inv2 f_eq f f')]), [mk e'] in let kinds = [`Hoare `Stmt; `EHoare `Stmt; `PHoare `Stmt; `Equiv `Stmt] in @@ -57,7 +57,7 @@ let process_change let pos = EcProofTyping.tc1_process_codepos tc (side, pos) in let expr (e : expr) ((hyps, m) : LDecl.hyps * memenv) = - let hyps = LDecl.push_active m hyps in + let hyps = LDecl.push_active_ss m hyps in let e = EcProofTyping.pf_process_exp !!tc hyps `InProc (Some e.e_ty) form @@ -80,26 +80,27 @@ let process_rewrite_rw let pts = EcHiGoal.LowRewrite.find_rewrite_patterns `LtoR pt in let change (e : expr) ((hyps, m) : LDecl.hyps * memenv) = - let e = form_of_expr (fst m) e in + let e = ss_inv_of_expr (fst m) e in let try1 (pt, mode, (f1, f2)) = try let subf, occmode = EcProofTerm.pf_find_occurence_lazy - pt.EcProofTerm.ptev_env ~ptn:f1 e + pt.EcProofTerm.ptev_env ~ptn:f1 e.inv in + let subf = { m=e.m; inv=subf } in assert (EcProofTerm.can_concretize pt.ptev_env); let f2 = EcProofTerm.concretize_form pt.ptev_env f2 in let pt, _ = EcProofTerm.concretize pt in - let cpos = + let cpos = EcMatching.FPosition.select_form ~xconv:`AlphaEq ~keyed:occmode.k_keyed - hyps None subf e in + hyps None subf.inv e.inv in - let e = EcMatching.FPosition.map cpos (fun _ -> f2) e in + let e = map_ss_inv1 (EcMatching.FPosition.map cpos (fun _ -> f2)) e in Some ((pt, mode, cpos), e) @@ -113,7 +114,7 @@ let process_rewrite_rw (fun () -> tc_error !!tc "cannot find a pattern to rewrite") (List.find_map try1 pts) in - (m, data), expr_of_form (fst m) e + (m, data), expr_of_ss_inv e in let pos = EcProofTyping.tc1_process_codepos tc (side, pos) in @@ -139,9 +140,9 @@ let process_rewrite_simpl let ri = EcReduction.nodelta in let change (e : expr) ((hyps, me) : LDecl.hyps * memenv) = - let f = form_of_expr (fst me) e in - let f = EcCallbyValue.norm_cbv ri hyps f in - let e = expr_of_form (fst me) f in + let f = ss_inv_of_expr (fst me) e in + let f = map_ss_inv1 (EcCallbyValue.norm_cbv ri hyps) f in + let e = expr_of_ss_inv f in (fst me, f), e in @@ -151,7 +152,7 @@ let change (e : expr) ((hyps, me) : LDecl.hyps * memenv) = FApi.t_first ( FApi.t_seqs [ EcLowGoal.t_intro_s (`Ident m); - EcLowGoal.t_change ~ri (f_eq f f); + EcLowGoal.t_change ~ri (map_ss_inv2 f_eq f f).inv; EcLowGoal.t_reflex ] ) tc diff --git a/src/phl/ecPhlRnd.ml b/src/phl/ecPhlRnd.ml index 780bf5708..67fa89267 100644 --- a/src/phl/ecPhlRnd.ml +++ b/src/phl/ecPhlRnd.ml @@ -6,6 +6,7 @@ open EcTypes open EcModules open EcFol open EcPV +open EcSubst open EcMatching.Position open EcCoreGoal @@ -15,10 +16,9 @@ open EcLowPhlGoal module TTC = EcProofTyping (* -------------------------------------------------------------------- *) -type chl_infos_t = (form, form option, form) rnd_tac_info -type bhl_infos_t = (form, ty -> form option, ty -> form) rnd_tac_info +type bhl_infos_t = (ss_inv, ty -> ss_inv option, ty -> ss_inv) rnd_tac_info type rnd_infos_t = (pformula, pformula option, pformula) rnd_tac_info -type mkbij_t = EcTypes.ty -> EcTypes.ty -> EcFol.form +type mkbij_t = EcTypes.ty -> EcTypes.ty -> ts_inv type semrndpos = (bool * codepos1) doption (* -------------------------------------------------------------------- *) @@ -28,15 +28,16 @@ module Core = struct let t_hoare_rnd_r tc = let env = FApi.tc1_env tc in let hs = tc1_as_hoareS tc in + let m = fst hs.hs_m in let (lv, distr), s = tc1_last_rnd tc hs.hs_s in let ty_distr = proj_distr_ty env (e_ty distr) in let x_id = EcIdent.create (symbol_of_lv lv) in - let x = f_local x_id ty_distr in - let distr = EcFol.form_of_expr (EcMemory.memory hs.hs_m) distr in - let post = subst_form_lv env (EcMemory.memory hs.hs_m) lv x hs.hs_po in - let post = f_imp (f_in_supp x distr) post in - let post = f_forall_simpl [(x_id,GTty ty_distr)] post in - let concl = f_hoareS_r {hs with hs_s=s; hs_po=post} in + let x = {m; inv=f_local x_id ty_distr} in + let distr = EcFol.ss_inv_of_expr m distr in + let post = subst_form_lv env lv x (hs_po hs) in + let post = map_ss_inv2 f_imp (map_ss_inv2 f_in_supp x distr) post in + let post = map_ss_inv1 (f_forall_simpl [(x_id,GTty ty_distr)]) post in + let concl = f_hoareS (snd hs.hs_m) (hs_pr hs) s post in FApi.xmutate1 tc `Rnd [concl] (* -------------------------------------------------------------------- *) @@ -47,39 +48,44 @@ module Core = struct let ty_distr = proj_distr_ty env (e_ty distr) in let x_id = EcIdent.create (symbol_of_lv lv) in let x = f_local x_id ty_distr in - let mem = EcMemory.memory hs.ehs_m in - let distr = EcFol.form_of_expr mem distr in - let post = subst_form_lv env mem lv x hs.ehs_po in - let post = f_Ep ty_distr distr (f_lambda [(x_id,GTty ty_distr)] post) in - let concl = f_eHoareS_r {hs with ehs_s=s; ehs_po=post } in + let m = fst hs.ehs_m in + let distr = EcFol.ss_inv_of_expr m distr in + let post = subst_form_lv env lv {m;inv=x} (ehs_po hs) in + let post = map_ss_inv2 (f_Ep ty_distr) distr + (map_ss_inv1 (f_lambda [(x_id,GTty ty_distr)]) post) in + let concl = f_eHoareS (snd hs.ehs_m) (ehs_pr hs) s post in FApi.xmutate1 tc `Rnd [concl] (* -------------------------------------------------------------------- *) let wp_equiv_disj_rnd_r side tc = let env = FApi.tc1_env tc in let es = tc1_as_equivS tc in - let m,s = + let ml, mr = fst es.es_ml, fst es.es_mr in + let m, mo, s = match side with - | `Left -> es.es_ml, es.es_sl - | `Right -> es.es_mr, es.es_sr + | `Left -> es.es_ml, fst es.es_mr, es.es_sl + | `Right -> es.es_mr, fst es.es_ml, es.es_sr in - + let subst_form_lv_side = sideif side subst_form_lv_left subst_form_lv_right in + let ss_inv_generalize_other = + sideif side ss_inv_generalize_right ss_inv_generalize_left in (* FIXME: exception when not rnds found *) let (lv, distr), s = tc1_last_rnd tc s in let ty_distr = proj_distr_ty env (e_ty distr) in let x_id = EcIdent.create (symbol_of_lv lv) in - let x = f_local x_id ty_distr in - - let distr = EcFol.form_of_expr (EcMemory.memory m) distr in - let post = subst_form_lv env (EcMemory.memory m) lv x es.es_po in - let post = f_imp (f_in_supp x distr) post in - let post = f_forall_simpl [(x_id,GTty ty_distr)] post in - let post = f_anda (f_lossless ty_distr distr) post in + let x = {ml; mr; inv=f_local x_id ty_distr} in + + let distr = EcFol.ss_inv_of_expr (EcMemory.memory m) distr in + let distr = ss_inv_generalize_other distr mo in + let post = subst_form_lv_side env lv x (es_po es) in + let post = map_ts_inv2 f_imp (map_ts_inv2 f_in_supp x distr) post in + let post = map_ts_inv1 (f_forall_simpl [(x_id,GTty ty_distr)]) post in + let post = map_ts_inv2 f_anda (map_ts_inv1 (f_lossless ty_distr) distr) post in let concl = match side with - | `Left -> f_equivS_r { es with es_sl=s; es_po=post; } - | `Right -> f_equivS_r { es with es_sr=s; es_po=post; } + | `Left -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) s es.es_sr post + | `Right -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) es.es_sl s post in FApi.xmutate1 tc `Rnd [concl] @@ -87,16 +93,17 @@ module Core = struct let wp_equiv_rnd_r bij tc = let env = FApi.tc1_env tc in let es = tc1_as_equivS tc in + let ml, mr = fst es.es_ml, fst es.es_mr in let (lvL, muL), sl' = tc1_last_rnd tc es.es_sl in let (lvR, muR), sr' = tc1_last_rnd tc es.es_sr in let tyL = proj_distr_ty env (e_ty muL) in let tyR = proj_distr_ty env (e_ty muR) in let xL_id = EcIdent.create (symbol_of_lv lvL ^ "L") and xR_id = EcIdent.create (symbol_of_lv lvR ^ "R") in - let xL = f_local xL_id tyL in - let xR = f_local xR_id tyR in - let muL = EcFol.form_of_expr (EcMemory.memory es.es_ml) muL in - let muR = EcFol.form_of_expr (EcMemory.memory es.es_mr) muR in + let xL = {ml;mr;inv=f_local xL_id tyL} in + let xR = {ml;mr;inv=f_local xR_id tyR} in + let muL = EcFol.ss_inv_of_expr ml muL in + let muR = EcFol.ss_inv_of_expr mr muR in let tf, tfinv = match bij with @@ -106,8 +113,8 @@ module Core = struct tc_error !!tc "%s, %s" "support are not compatible" "an explicit bijection is required"; - (EcFol.f_identity ~name:"z" tyL, - EcFol.f_identity ~name:"z" tyR) + ({ml;mr;inv=EcFol.f_identity ~name:"z" tyL}, + {ml;mr;inv=EcFol.f_identity ~name:"z" tyR}) in (* (∀ x₂, x₂ ∈ ℑ(D₂) ⇒ x₂ = f(f⁻¹(x₂)) @@ -115,27 +122,30 @@ module Core = struct * && (∀ x₁, x₁ ∈ ℑ(D₁) ⇒ f(x₁) ∈ ℑ(D₂) && x₁ = f⁻¹(f(x₁)) && φ(x₁, f(x₁))) *) - let f t = f_app_simpl tf [t] tyR in - let finv t = f_app_simpl tfinv [t] tyL in + let f_app_simpl' ty f t = f_app_simpl f [t] ty in + let f t = map_ts_inv2 (f_app_simpl' tyR) tf t in + let finv t = map_ts_inv2 (f_app_simpl' tyL) tfinv t in + + let post = subst_form_lv_left env lvL xL (es_po es) in + let post = subst_form_lv_right env lvR (f xL) post in - let cond_fbij = f_eq xL (finv (f xL)) in - let cond_fbij_inv = f_eq xR (f (finv xR)) in + let muL = ss_inv_generalize_right muL mr in + let muR = ss_inv_generalize_left muR ml in - let post = es.es_po in - let post = subst_form_lv env (EcMemory.memory es.es_ml) lvL xL post in - let post = subst_form_lv env (EcMemory.memory es.es_mr) lvR (f xL) post in + let cond_fbij = map_ts_inv2 f_eq xL (finv (f xL)) in + let cond_fbij_inv = map_ts_inv2 f_eq xR (f (finv xR)) in - let cond1 = f_imp (f_in_supp xR muR) cond_fbij_inv in - let cond2 = f_imp (f_in_supp xR muR) (f_eq (f_mu_x muR xR) (f_mu_x muL (finv xR))) in - let cond3 = f_andas [f_in_supp (f xL) muR; cond_fbij; post] in - let cond3 = f_imp (f_in_supp xL muL) cond3 in + let cond1 = map_ts_inv2 f_imp (map_ts_inv2 f_in_supp xR muR) cond_fbij_inv in + let cond2 = map_ts_inv2 f_imp (map_ts_inv2 f_in_supp xR muR) (map_ts_inv2 f_eq (map_ts_inv2 f_mu_x muR xR) (map_ts_inv2 f_mu_x muL (finv xR))) in + let cond3 = map_ts_inv f_andas [map_ts_inv2 f_in_supp (f xL) muR; cond_fbij; post] in + let cond3 = map_ts_inv2 f_imp (map_ts_inv2 f_in_supp xL muL) cond3 in - let concl = f_andas - [f_forall_simpl [(xR_id, GTty tyR)] cond1; - f_forall_simpl [(xR_id, GTty tyR)] cond2; - f_forall_simpl [(xL_id, GTty tyL)] cond3] in + let concl = map_ts_inv f_andas + [map_ts_inv1 (f_forall_simpl [(xR_id, GTty tyR)]) cond1; + map_ts_inv1 (f_forall_simpl [(xR_id, GTty tyR)]) cond2; + map_ts_inv1 (f_forall_simpl [(xL_id, GTty tyL)]) cond3] in - let concl = f_equivS_r { es with es_sl=sl'; es_sr=sr'; es_po=concl; } in + let concl = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl' sr' concl in FApi.xmutate1 tc `Rnd [concl] @@ -145,20 +155,22 @@ module Core = struct let bhs = tc1_as_bdhoareS tc in let (lv,distr),s = tc1_last_rnd tc bhs.bhs_s in let ty_distr = proj_distr_ty env (e_ty distr) in - let distr = EcFol.form_of_expr (EcMemory.memory bhs.bhs_m) distr in + let distr = EcFol.ss_inv_of_expr (EcMemory.memory bhs.bhs_m) distr in let m = fst bhs.bhs_m in let mk_event_cond event = let v_id = EcIdent.create "v" in - let v = f_local v_id ty_distr in - let post_v = subst_form_lv env (EcMemory.memory bhs.bhs_m) lv v bhs.bhs_po in - let event_v = f_app event [v] tbool in - let v_in_supp = f_in_supp v distr in - f_forall_simpl [v_id,GTty ty_distr] + let v = {m; inv=f_local v_id ty_distr} in + let post_v = subst_form_lv env lv v (bhs_po bhs) in + let f_app' fl = f_app (List.hd fl) (List.tl fl) tbool in + let event_v = map_ss_inv f_app' [event ;v] in + let v_in_supp = map_ss_inv2 f_in_supp v distr in + map_ss_inv1 (f_forall_simpl [v_id,GTty ty_distr]) begin + let f_imps_simpl' fl = f_imps_simpl (List.tl fl) (List.hd fl) in match bhs.bhs_cmp with - | FHle -> f_imps_simpl [v_in_supp;post_v] event_v - | FHge -> f_imps_simpl [v_in_supp;event_v] post_v - | FHeq -> f_imp_simpl v_in_supp (f_iff_simpl event_v post_v) + | FHle -> map_ss_inv f_imps_simpl' [event_v; v_in_supp;post_v] + | FHge -> map_ss_inv f_imps_simpl' [post_v; v_in_supp;event_v] + | FHeq -> map_ss_inv2 f_imp_simpl v_in_supp (map_ss_inv2 f_iff_simpl event_v post_v) end in let f_cmp = match bhs.bhs_cmp with @@ -167,14 +179,14 @@ module Core = struct | FHeq -> f_eq in let is_post_indep = - let fv = EcPV.PV.fv env m bhs.bhs_po in + let fv = EcPV.PV.fv env (bhs_po bhs).m (bhs_po bhs).inv in match lv with | LvVar (x,_) -> not (EcPV.PV.mem_pv env x fv) | LvTuple pvs -> List.for_all (fun (x,_) -> not (EcPV.PV.mem_pv env x fv)) pvs in let is_bd_indep = - let fv_bd = PV.fv env mhr bhs.bhs_bd in + let fv_bd = PV.fv env (bhs_bd bhs).m (bhs_bd bhs).inv in let modif_s = s_write env s in PV.indep env modif_s fv_bd in @@ -189,78 +201,84 @@ module Core = struct in let bound,pre_bound,binders = if is_bd_indep then - bhs.bhs_bd, f_true, [] + bhs_bd bhs, {m;inv=f_true}, [] else let bd_id = EcIdent.create "bd" in - let bd = f_local bd_id treal in - bd, f_eq bhs.bhs_bd bd, [(bd_id,GTty treal)] + let bd = {m;inv=f_local bd_id treal} in + bd, map_ss_inv2 f_eq (bhs_bd bhs) bd, [(bd_id,GTty treal)] in let subgoals = match tac_info, bhs.bhs_cmp with | PNoRndParams, FHle -> if is_post_indep then (* event is true *) - let concl = f_bdHoareS_r {bhs with bhs_s=s} in + let concl = f_bdHoareS (snd bhs.bhs_m) + (bhs_pr bhs) s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in [concl] else - let event = mk_event ty_distr in - let bounded_distr = f_real_le (f_mu env distr event) bound in - let pre = f_and bhs.bhs_pr pre_bound in - let post = f_anda bounded_distr (mk_event_cond event) in - let concl = f_hoareS bhs.bhs_m pre s post in + let event = {m; inv=mk_event ty_distr} in + let bounded_distr = map_ss_inv2 f_real_le (map_ss_inv2 (f_mu env) distr event) bound in + let pre = map_ss_inv2 f_and (bhs_pr bhs) pre_bound in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + let concl = f_hoareS (snd bhs.bhs_m) pre s post in let concl = f_forall_simpl binders concl in [concl] | PNoRndParams, _ -> if is_post_indep then (* event is true *) - let event = mk_event ty_distr in - let bounded_distr = f_eq (f_mu env distr event) f_r1 in - let concl = f_bdHoareS_r - {bhs with bhs_s=s; bhs_po=f_and bhs.bhs_po bounded_distr} in + let event = {m;inv=mk_event ty_distr} in + let f_r1 = {m;inv=f_r1} in + let bounded_distr = map_ss_inv2 f_eq (map_ss_inv2 (f_mu env) distr event) f_r1 in + let post = map_ss_inv2 f_and (bhs_po bhs) bounded_distr in + let concl = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) s post bhs.bhs_cmp (bhs_bd bhs) in [concl] else - let event = mk_event ty_distr in - let bounded_distr = f_cmp (f_mu env distr event) bound in - let pre = f_and bhs.bhs_pr pre_bound in - let post = f_anda bounded_distr (mk_event_cond event) in - let concl = f_bdHoareS_r {bhs with bhs_s=s; bhs_pr=pre; bhs_po=post; bhs_bd=f_r1} in + let event = {m;inv=mk_event ty_distr} in + let bounded_distr = map_ss_inv2 f_cmp (map_ss_inv2 (f_mu env) distr event) bound in + let pre = map_ss_inv2 f_and (bhs_pr bhs) pre_bound in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + let concl = f_bdHoareS (snd bhs.bhs_m) pre s post bhs.bhs_cmp {m;inv=f_r1} in let concl = f_forall_simpl binders concl in [concl] | PSingleRndParam event, FHle -> let event = event ty_distr in - let bounded_distr = f_real_le (f_mu env distr event) bound in - let pre = f_and bhs.bhs_pr pre_bound in - let post = f_anda bounded_distr (mk_event_cond event) in - let concl = f_hoareS bhs.bhs_m pre s post in + let bounded_distr = map_ss_inv2 f_real_le (map_ss_inv2 (f_mu env) distr event) bound in + let pre = map_ss_inv2 f_and (bhs_pr bhs) pre_bound in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + let concl = f_hoareS (snd bhs.bhs_m) pre s post in let concl = f_forall_simpl binders concl in [concl] | PSingleRndParam event, _ -> let event = event ty_distr in - let bounded_distr = f_cmp (f_mu env distr event) bound in - let pre = f_and bhs.bhs_pr pre_bound in - let post = f_anda bounded_distr (mk_event_cond event) in - let concl = f_bdHoareS_r {bhs with bhs_s=s; bhs_pr=pre; bhs_po=post; bhs_cmp=FHeq; bhs_bd=f_r1} in + let bounded_distr = map_ss_inv2 f_cmp (map_ss_inv2 (f_mu env) distr event) bound in + let pre = map_ss_inv2 f_and (bhs_pr bhs) pre_bound in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + let concl = f_bdHoareS (snd bhs.bhs_m) pre s post FHeq {m;inv=f_r1} in let concl = f_forall_simpl binders concl in [concl] | PMultRndParams ((phi,d1,d2,d3,d4),event), _ -> let event = match event ty_distr with - | None -> mk_event ~simpl:false ty_distr | Some event -> event + | None -> {m;inv=mk_event ~simpl:false ty_distr} | Some event -> event in - let bd_sgoal = f_cmp (f_real_add (f_real_mul d1 d2) (f_real_mul d3 d4)) bhs.bhs_bd in - let sgoal1 = f_bdHoareS_r {bhs with bhs_s=s; bhs_po=phi; bhs_bd=d1} in + let bd_sgoal = map_ss_inv2 f_cmp (map_ss_inv2 f_real_add (map_ss_inv2 f_real_mul d1 d2) (map_ss_inv2 f_real_mul d3 d4)) (bhs_bd bhs) in + let bd_sgoal = f_forall_mems_ss_inv (bhs.bhs_m) bd_sgoal in + let sgoal1 = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) s phi bhs.bhs_cmp d1 in let sgoal2 = - let bounded_distr = f_cmp (f_mu env distr event) d2 in - let post = f_anda bounded_distr (mk_event_cond event) in - f_forall_mems [bhs.bhs_m] (f_imp phi post) + let bounded_distr = map_ss_inv2 f_cmp (map_ss_inv2 (f_mu env) distr event) d2 in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + f_forall_mems_ss_inv (bhs.bhs_m) (map_ss_inv2 f_imp phi post) in - let sgoal3 = f_bdHoareS_r {bhs with bhs_s=s; bhs_po=f_not phi; bhs_bd=d3} in + let sgoal3 = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) s (map_ss_inv1 f_not phi) bhs.bhs_cmp d3 in let sgoal4 = - let bounded_distr = f_cmp (f_mu env distr event) d4 in - let post = f_anda bounded_distr (mk_event_cond event) in - f_forall_mems [bhs.bhs_m] (f_imp (f_not phi) post) in + let bounded_distr = map_ss_inv2 f_cmp (map_ss_inv2 (f_mu env) distr event) d4 in + let post = map_ss_inv2 f_anda bounded_distr (mk_event_cond event) in + f_forall_mems_ss_inv bhs.bhs_m (map_ss_inv2 f_imp (map_ss_inv1 f_not phi) post) in let sgoal5 = - let f_inbound x = f_anda (f_real_le f_r0 x) (f_real_le x f_r1) in - f_ands (List.map f_inbound [d1; d2; d3; d4]) + let f_inbound x = + let f_r1, f_r0 = {m;inv=f_r1}, {m;inv=f_r0} in + map_ss_inv2 f_anda (map_ss_inv2 f_real_le f_r0 x) (map_ss_inv2 f_real_le x f_r1) in + map_ss_inv f_ands (List.map f_inbound [d1; d2; d3; d4]) in + let sgoal5 = f_forall_mems_ss_inv (bhs.bhs_m) sgoal5 in [bd_sgoal;sgoal1;sgoal2;sgoal3;sgoal4;sgoal5] | _, _ -> tc_error !!tc "invalid arguments" @@ -310,61 +328,63 @@ module Core = struct compare (PVMap.find pv1 m) (PVMap.find pv2 m)) wr in - let rec do1 (subst : PVM.subst) (s : instr list) = + let rec do1 (m: memory) (subst : PVM.subst) (s : instr list) = match s with | [] -> let tuple = List.map (fun (pv, _) -> - PVM.find env pv mhr subst) wr in - f_dunit (f_tuple tuple) + PVM.find env pv m subst) wr in + {m;inv=f_dunit (f_tuple tuple)} | { i_node = Sasgn (lv, e) } :: s -> - let e = form_of_expr mhr e in - let e = PVM.subst env subst e in + let e = ss_inv_of_expr m e in + let e = map_ss_inv1 (PVM.subst env subst) e in let subst = match lv with | LvVar (pv, _) -> - PVM.add env pv mhr e subst + PVM.add env pv m e.inv subst | LvTuple pvs -> List.fold_lefti (fun subst i (pv, ty) -> - PVM.add env pv mhr (f_proj e i ty) subst + PVM.add env pv m (f_proj e.inv i ty) subst ) subst pvs in - do1 subst s + do1 m subst s | { i_node = Srnd (lv, d) } :: s -> - let d = form_of_expr mhr d in - let d = PVM.subst env subst d in + let d = ss_inv_of_expr m d in + let d = map_ss_inv1 (PVM.subst env subst) d in let x = EcIdent.create (name_of_lv lv) in let subst, xty = match lv with | LvVar (pv, ty) -> let x = f_local x ty in - (PVM.add env pv mhr x subst, ty) + (PVM.add env pv m x subst, ty) | LvTuple pvs -> let ty = ttuple (List.snd pvs) in let x = f_local x ty in let subst = List.fold_lefti (fun subst i (pv, ty) -> - PVM.add env pv mhr (f_proj x i ty) subst + PVM.add env pv m (f_proj x i ty) subst ) subst pvs in (subst, ty) in - let body = do1 subst s in + let body = do1 m subst s in - f_dlet_simpl + map_ss_inv2 + (f_dlet_simpl xty - (ttuple (List.snd wr)) + (ttuple (List.snd wr))) d - (f_lambda [(x, GTty xty)] body) + (map_ss_inv1 (f_lambda [(x, GTty xty)]) body) | _ :: _ -> error () in - let distr = do1 PVM.empty s in - let distr = expr_of_form mhr distr in + let mhr = EcIdent.create "&hr" in + let distr = do1 mhr PVM.empty s in + let distr = expr_of_ss_inv distr in match lv_of_list wr with | None -> @@ -384,9 +404,9 @@ module Core = struct if reduce then Some (PV.fv (FApi.tc1_env tc) (fst hs.hs_m) hs.hs_po) else None in - let m, s2 = semrnd tc hs.hs_m fv s2 in - let concl = { hs with hs_s = stmt (s1 @ s2); hs_m = m; } in - FApi.xmutate1 tc (`RndSem pos) [f_hoareS_r concl] + let (_, mt), s2 = semrnd tc hs.hs_m fv s2 in + let concl = f_hoareS mt (hs_pr hs) (stmt (s1 @ s2)) (hs_po hs) in + FApi.xmutate1 tc (`RndSem pos) [concl] (* -------------------------------------------------------------------- *) let t_bdhoare_rndsem_r reduce pos tc = @@ -397,9 +417,9 @@ module Core = struct if reduce then Some (PV.fv (FApi.tc1_env tc) (fst bhs.bhs_m) bhs.bhs_po) else None in - let m, s2 = semrnd tc bhs.bhs_m fv s2 in - let concl = { bhs with bhs_s = stmt (s1 @ s2); bhs_m = m; } in - FApi.xmutate1 tc (`RndSem pos) [f_bdHoareS_r concl] + let (_,mt), s2 = semrnd tc bhs.bhs_m fv s2 in + let concl = f_bdHoareS mt (bhs_pr bhs) (stmt (s1 @ s2)) (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in + FApi.xmutate1 tc (`RndSem pos) [concl] (* -------------------------------------------------------------------- *) let t_equiv_rndsem_r reduce side pos tc = @@ -414,13 +434,13 @@ module Core = struct if reduce then Some (PV.fv (FApi.tc1_env tc) (fst m) es.es_po) else None in - let m, s2 = semrnd tc m fv s2 in + let (_,mt), s2 = semrnd tc m fv s2 in let s = stmt (s1 @ s2) in let concl = match side with - | `Left -> { es with es_sl = s; es_ml = m; } - | `Right -> { es with es_sr = s; es_mr = m; } in - FApi.xmutate1 tc (`RndSem pos) [f_equivS_r concl] + | `Left -> f_equivS mt (snd es.es_mr) (es_pr es) s es.es_sr (es_po es) + | `Right -> f_equivS (snd es.es_ml) mt (es_pr es) es.es_sl s (es_po es) in + FApi.xmutate1 tc (`RndSem pos) [concl] end (* Core *) @@ -456,8 +476,8 @@ let wp_equiv_disj_rnd_r side tc = let tc = Core.wp_equiv_disj_rnd_r side tc in let es = tc1_as_equivS (FApi.as_tcenv1 tc) in - let c1, c2 = destr_and es.es_po in - let newc1 = EcFol.f_forall_mems [es.es_ml; es.es_mr] c1 in + let (c1, c2) = map_ts_inv_destr2 destr_and (es_po es) in + let newc1 = EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr c1 in let subtc = tc in let subtc, hdc1 = solve 2 newc1 subtc in @@ -481,7 +501,7 @@ let wp_equiv_disj_rnd_r side tc = | _ -> EcLowGoal.t_id) (FApi.t_first - (EcPhlConseq.t_equivS_conseq es.es_pr po) + (EcPhlConseq.t_equivS_conseq (es_pr es) po) subtc) (* -------------------------------------------------------------------- *) @@ -489,12 +509,14 @@ let wp_equiv_rnd_r bij tc = let tc = Core.wp_equiv_rnd_r bij tc in let es = tc1_as_equivS (FApi.as_tcenv1 tc) in - let c1, c2, c3 = destr_and3 es.es_po in - let (x, xty, c3) = destr_forall1 c3 in - let ind, (c3, c4) = snd_map destr_and (destr_imp c3) in - let newc2 = EcFol.f_forall_mems [es.es_ml; es.es_mr] c2 in - let newc3 = EcFol.f_forall_mems [es.es_ml; es.es_mr] - (f_forall [x, xty] (f_imp ind c3)) in + let c1, c2, c3 = map_ts_inv_destr3 destr_and3 (es_po es) in + let (x, xty, _) = destr_forall1 c3.inv in + let c3 = map_ts_inv1 (fun c3 -> let (_,_,d) = destr_forall1 c3 in d) c3 in + let (ind, c3) = map_ts_inv_destr2 destr_imp c3 in + let (c3, c4) = map_ts_inv_destr2 destr_and c3 in + let newc2 = EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr c2 in + let newc3 = EcSubst.f_forall_mems_ts_inv es.es_ml es.es_mr + (map_ts_inv1 (f_forall [x, xty]) (map_ts_inv2 f_imp ind c3)) in let subtc = tc in let subtc, hdc2 = solve 4 newc2 subtc in @@ -503,9 +525,12 @@ let wp_equiv_rnd_r bij tc = let po = match hdc2, hdc3 with | None , None -> None - | Some _, Some _ -> Some (f_anda c1 (f_forall [x, xty] (f_imp ind c4))) - | Some _, None -> Some (f_anda c1 (f_forall [x, xty] (f_imp ind (f_anda c3 c4)))) - | None , Some _ -> Some (f_andas [c1; c2; f_forall [x, xty] (f_imp ind c4)]) + | Some _, Some _ -> + Some (map_ts_inv2 f_anda c1 (map_ts_inv1 (f_forall [x, xty]) (map_ts_inv2 f_imp ind c4))) + | Some _, None -> + Some (map_ts_inv2 f_anda c1 (map_ts_inv1 (f_forall [x, xty]) (map_ts_inv2 f_imp ind (map_ts_inv2 f_anda c3 c4)))) + | None , Some _ -> + Some (map_ts_inv f_andas [c1; c2; map_ts_inv1 (f_forall [x, xty]) (map_ts_inv2 f_imp ind c4)]) in match po with None -> tc | Some po -> @@ -557,7 +582,7 @@ let wp_equiv_rnd_r bij tc = | _ -> EcLowGoal.t_id) (FApi.t_first - (EcPhlConseq.t_equivS_conseq es.es_pr po) + (EcPhlConseq.t_equivS_conseq (es_pr es) po) subtc) (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlRnd.mli b/src/phl/ecPhlRnd.mli index 29d6865e2..e636ac6d9 100644 --- a/src/phl/ecPhlRnd.mli +++ b/src/phl/ecPhlRnd.mli @@ -1,16 +1,14 @@ (* -------------------------------------------------------------------- *) open EcUtils open EcParsetree -open EcTypes -open EcFol open EcCoreGoal.FApi open EcMatching.Position +open EcAst (* -------------------------------------------------------------------- *) -type chl_infos_t = (form, form option, form) rnd_tac_info -type bhl_infos_t = (form, ty -> form option, ty -> form) rnd_tac_info +type bhl_infos_t = (ss_inv, ty -> ss_inv option, ty -> ss_inv) rnd_tac_info type rnd_infos_t = (pformula, pformula option, pformula) rnd_tac_info -type mkbij_t = EcTypes.ty -> EcTypes.ty -> EcFol.form +type mkbij_t = EcTypes.ty -> EcTypes.ty -> ts_inv (* -------------------------------------------------------------------- *) val wp_equiv_disj_rnd : side -> backward diff --git a/src/phl/ecPhlRwEquiv.ml b/src/phl/ecPhlRwEquiv.ml index 767138a3a..b47d05084 100644 --- a/src/phl/ecPhlRwEquiv.ml +++ b/src/phl/ecPhlRwEquiv.ml @@ -4,6 +4,7 @@ open EcParsetree open EcFol open EcModules open EcPath +open EcAst open EcCoreGoal open EcCoreGoal.FApi @@ -85,7 +86,7 @@ let t_rewrite_equiv side dir cp (equiv : equivF) equiv_pt rargslv tc = | `Left, `RtoL -> EcPhlSym.t_equiv_sym | `Right, `LtoR -> EcPhlSym.t_equiv_sym | `Right, `RtoL -> t_id); - EcPhlCall.t_call None (f_equivF_r equiv); + EcPhlCall.t_call None (f_equivF (ef_pr equiv) equiv.ef_fl equiv.ef_fr (ef_po equiv)); t_try (t_apply equiv_pt); (* FIXME: Can do better here, we know this applies to just the first sub goal of call *) t_try (t_seqs [ EcPhlInline.process_inline (`ByName (None, None, ([], None))); @@ -139,7 +140,7 @@ let process_rewrite_equiv info tc = begin try let proc = EcEnv.Fun.by_xpath new_func env in - let subenv = EcEnv.Memory.push_active mem env in + let subenv = EcEnv.Memory.push_active_ss mem env in let ue = EcUnify.UniEnv.create (Some []) in let args, ret_ty = EcTyping.trans_args subenv ue (loc pargs) proc.f_sig (unloc pargs) in let res = omap (fun v -> EcTyping.transexpcast subenv `InProc ue ret_ty v) pres in diff --git a/src/phl/ecPhlSkip.ml b/src/phl/ecPhlSkip.ml index 4496b205d..31d15741b 100644 --- a/src/phl/ecPhlSkip.ml +++ b/src/phl/ecPhlSkip.ml @@ -58,6 +58,8 @@ module LowInternal = struct (* ------------------------------------------------------------------ *) let t_bdhoare_skip_r tc = let t_trivial = FApi.t_seqs [t_simplify ~delta:`No; t_split; t_fail] in + let bhs = tc1_as_bdhoareS tc in + let f_r1: EcAst.ss_inv = {m=fst bhs.bhs_m; inv=f_r1} in let t_conseq = EcPhlConseq.t_bdHoareS_conseq_bd FHeq f_r1 in FApi.t_internal (FApi.t_seqsub t_conseq diff --git a/src/phl/ecPhlSp.ml b/src/phl/ecPhlSp.ml index 91f9167d2..0d2855282 100644 --- a/src/phl/ecPhlSp.ml +++ b/src/phl/ecPhlSp.ml @@ -50,6 +50,7 @@ module LowInternal = struct (* ------------------------------------------------------------------ *) let sp_asgn (memenv : EcMemory.memenv) env lv e (bds, assoc, pre) = + let m = fst memenv in let subst_in_assoc lv new_id_exp new_ids ((ass : assignables), f) = let replace_assignable var = match var with @@ -72,7 +73,7 @@ module LowInternal = struct | _ -> var in let ass = List.map replace_assignable ass in - let f = subst_form_lv env (EcMemory.memory memenv) lv new_id_exp f in + let f = (subst_form_lv env lv {m;inv=new_id_exp} {m;inv=f}).inv in (ass, f) in @@ -104,15 +105,15 @@ module LowInternal = struct in let for_lvars vs = - let mem = EcMemory.memory memenv in - let fresh pv = EcIdent.create (EcIdent.name (id_of_pv pv mem)) in + let m = EcMemory.memory memenv in + let fresh pv = EcIdent.create (EcIdent.name (id_of_pv pv m)) in let newids = List.map (fst_map fresh) vs in let bds = newids @ bds in let astuple = f_tuple (List.map (curry f_local) newids) in - let pre = subst_form_lv env mem lv astuple pre in - let e_form = EcFol.form_of_expr mem e in - let e_form = subst_form_lv env mem lv astuple e_form in + let pre = (subst_form_lv env lv {m;inv=astuple} {m;inv=pre}).inv in + let e_form = EcFol.ss_inv_of_expr m e in + let e_form = (subst_form_lv env lv {m;inv=astuple} e_form).inv in let assoc = (List.map (fun x -> APVar x) vs, e_form) @@ -130,7 +131,7 @@ module LowInternal = struct (* ------------------------------------------------------------------ *) let build_sp (memenv : EcMemory.memenv) bds assoc pre = let f_assoc = function - | APVar (pv, pv_ty) -> f_pvar pv pv_ty (EcMemory.memory memenv) + | APVar (pv, pv_ty) -> (f_pvar pv pv_ty (EcMemory.memory memenv)).inv | ALocal (lv, lv_ty) -> f_local lv lv_ty in @@ -185,7 +186,7 @@ module LowInternal = struct bds, assoc, pre | Sif (e, s1, s2) -> - let e_form = EcFol.form_of_expr (EcMemory.memory memenv) e in + let e_form = (EcFol.ss_inv_of_expr (EcMemory.memory memenv) e).inv in let pre_t = build_sp memenv bds assoc (f_and_simpl e_form pre) in let pre_f = @@ -242,9 +243,10 @@ let t_sp_side pos tc = | FhoareS hs, (None | Some (Single _)) -> let pos = pos |> omap as_single in let stmt1, stmt2 = o_split ~rev:true env pos hs.hs_s in - let stmt1, hs_pr = LI.sp_stmt hs.hs_m env stmt1 hs.hs_pr in + let stmt1, hs_pr = LI.sp_stmt hs.hs_m env stmt1 (hs_pr hs).inv in check_sp_progress pos stmt1; - let subgoal = f_hoareS_r { hs with hs_s = stmt (stmt1@stmt2); hs_pr } in + let m = fst hs.hs_m in + let subgoal = f_hoareS (snd hs.hs_m) {m;inv=hs_pr} (stmt (stmt1@stmt2)) (hs_po hs) in FApi.xmutate1 tc `Sp [subgoal] @@ -252,9 +254,10 @@ let t_sp_side pos tc = let pos = pos |> omap as_single in let stmt1, stmt2 = o_split ~rev:true env pos bhs.bhs_s in check_form_indep stmt1 bhs.bhs_m bhs.bhs_bd; - let stmt1, bhs_pr = LI.sp_stmt bhs.bhs_m env stmt1 bhs.bhs_pr in + let stmt1, bhs_pr = LI.sp_stmt bhs.bhs_m env stmt1 (bhs_pr bhs).inv in check_sp_progress pos stmt1; - let subgoal = f_bdHoareS_r {bhs with bhs_s = stmt (stmt1@stmt2); bhs_pr; } in + let m = fst bhs.bhs_m in + let subgoal = f_bdHoareS (snd bhs.bhs_m) {m;inv=bhs_pr} (stmt (stmt1@stmt2)) (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `Sp [subgoal] | FequivS es, (None | Some (Double _)) -> @@ -265,18 +268,16 @@ let t_sp_side pos tc = let stmtL1, stmtL2 = o_split ~rev:true env posL es.es_sl in let stmtR1, stmtR2 = o_split ~rev:true env posR es.es_sr in - let es_pr = es.es_pr in - let stmtL1, es_pr = LI.sp_stmt es.es_ml env stmtL1 es_pr in + let es_pr = (es_pr es) in + let stmtL1, es_pr = LI.sp_stmt es.es_ml env stmtL1 es_pr.inv in let stmtR1, es_pr = LI.sp_stmt es.es_mr env stmtR1 es_pr in + let ml, mr = fst es.es_ml, fst es.es_mr in + check_sp_progress ~side:`Left pos stmtL1; check_sp_progress ~side:`Right pos stmtR1; - let subgoal = f_equivS_r { es with - es_sl = stmt (stmtL1@stmtL2); - es_sr = stmt (stmtR1@stmtR2); - es_pr =es_pr; - } in + let subgoal = f_equivS (snd es.es_ml) (snd es.es_mr) {ml;mr;inv=es_pr} (stmt (stmtL1@stmtL2)) (stmt (stmtR1@stmtR2)) (es_po es) in FApi.xmutate1 tc `Sp [subgoal] diff --git a/src/phl/ecPhlSwap.ml b/src/phl/ecPhlSwap.ml index 0342a414d..ff641f692 100644 --- a/src/phl/ecPhlSwap.ml +++ b/src/phl/ecPhlSwap.ml @@ -160,7 +160,7 @@ let rec process_swap1 (info : (oside * pswap_kind) located) (tc : tcenv1) = let me, _ = EcLowPhlGoal.tc1_get_stmt side tc in let process_codepos = - let env = EcEnv.Memory.push_active me env in + let env = EcEnv.Memory.push_active_ss me env in fun p -> EcTyping.trans_codepos1 env p in let process_codeoffset (o : pcodeoffset1) : codeoffset1 = diff --git a/src/phl/ecPhlSym.ml b/src/phl/ecPhlSym.ml index 898d5349f..50836bc8c 100644 --- a/src/phl/ecPhlSym.ml +++ b/src/phl/ecPhlSym.ml @@ -2,33 +2,25 @@ open EcFol open EcCoreGoal open EcLowPhlGoal - -(*-------------------------------------------------------------------- *) -let build_sym ml mr pr po = - let s = Fsubst.f_subst_id in - let s = Fsubst.f_bind_mem s ml mr in - let s = Fsubst.f_bind_mem s mr ml in - let s = Fsubst.f_subst s in - (s pr, s po) +open EcAst +open EcSubst (*-------------------------------------------------------------------- *) let t_equivF_sym tc = let ef = tc1_as_equivF tc in - let pr,po = build_sym mleft mright ef.ef_pr ef.ef_po in + let mr, ml = ef.ef_ml, ef.ef_mr in + let pr = ts_inv_rebind (ef_pr ef) mr ml in + let po = ts_inv_rebind (ef_po ef) mr ml in let cond = f_equivF pr ef.ef_fr ef.ef_fl po in FApi.xmutate1 tc `EquivSym [cond] (*-------------------------------------------------------------------- *) let t_equivS_sym tc = let es = tc1_as_equivS tc in - let pr,po = build_sym (fst es.es_ml) (fst es.es_mr) es.es_pr es.es_po in - let cond = f_equivS_r { - es_ml = fst es.es_ml, snd es.es_mr; - es_mr = fst es.es_mr, snd es.es_ml; - es_sl = es.es_sr; - es_sr = es.es_sl; - es_pr = pr; - es_po = po; } in + let (mr, mtr), (ml, mtl) = es.es_ml, es.es_mr in + let pr = ts_inv_rebind (es_pr es) mr ml in + let po = ts_inv_rebind (es_po es) mr ml in + let cond = f_equivS mtr mtl pr es.es_sr es.es_sl po in FApi.xmutate1 tc `EquivSym [cond] diff --git a/src/phl/ecPhlTAuto.ml b/src/phl/ecPhlTAuto.ml index 02ac79a43..4e6fe3d38 100644 --- a/src/phl/ecPhlTAuto.ml +++ b/src/phl/ecPhlTAuto.ml @@ -1,5 +1,6 @@ (* -------------------------------------------------------------------- *) open EcFol +open EcAst open EcCoreGoal open EcLowPhlGoal @@ -7,10 +8,10 @@ open EcLowPhlGoal (* -------------------------------------------------------------------- *) let t_hoare_true_r tc = match (FApi.tc1_goal tc).f_node with - | FhoareF hf when f_equal hf.hf_po f_true -> + | FhoareF hf when f_equal (hf_po hf).inv f_true -> FApi.xmutate1 tc `HoareTrue [] - | FhoareS hs when f_equal hs.hs_po f_true -> + | FhoareS hs when f_equal (hs_po hs).inv f_true -> FApi.xmutate1 tc `HoareTrue [] | _ -> @@ -40,7 +41,7 @@ let t_ehoare_zero = FApi.t_low0 "hoare-zero" t_ehoare_zero_r (* -------------------------------------------------------------------- *) let t_core_exfalso_r tc = let pre = tc1_get_pre tc in - if not (f_equal pre f_false) then + if not (f_equal (inv_of_inv pre) f_false) then tc_error !!tc "pre-condition is not `false'"; FApi.xmutate1 tc `ExFalso [] diff --git a/src/phl/ecPhlTrans.ml b/src/phl/ecPhlTrans.ml index 6bf9d9910..c6976e6be 100644 --- a/src/phl/ecPhlTrans.ml +++ b/src/phl/ecPhlTrans.ml @@ -8,6 +8,7 @@ open EcPV open EcMatching open EcTransMatching open EcMaps +open EcAst open EcCoreGoal open EcLowPhlGoal @@ -17,23 +18,25 @@ module TTC = EcProofTyping (* -------------------------------------------------------------------- *) module Low = struct (* ------------------------------------------------------------------ *) - let transitivity_side_cond hyps prml prmr poml pomr p q p1 q1 pomt p2 q2 = + let transitivity_side_cond hyps prml prmr poml pomr p q (p1: ts_inv) (q1: ts_inv) pomt (p2: ts_inv) (q2: ts_inv) = let env = LDecl.toenv hyps in let cond1 = - let fv1 = PV.fv env mright p1 in - let fv2 = PV.fv env mleft p2 in + let fv1 = PV.fv env p1.mr p1.inv in + let fv2 = PV.fv env p2.ml p2.inv in let fv = PV.union fv1 fv2 in let elts, glob = PV.ntr_elements fv in - let bd, s = generalize_subst env mhr elts glob in - let s1 = PVM.of_mpv s mright in - let s2 = PVM.of_mpv s mleft in - let concl = f_and (PVM.subst env s1 p1) (PVM.subst env s2 p2) in - f_forall_mems [prml;prmr] (f_imp p (f_exists bd concl)) in + let m = EcIdent.create "&m" in + let bd, s = generalize_subst env m elts glob in + let s1 = PVM.of_mpv s p.mr in + let s2 = PVM.of_mpv s p.ml in + let concl = map_ts_inv2 f_and (map_ts_inv1 (PVM.subst env s1) p1) (map_ts_inv1 (PVM.subst env s2) p2) in + EcSubst.f_forall_mems_ts_inv prml prmr (map_ts_inv2 f_imp p (map_ts_inv1 (f_exists bd) concl)) in let cond2 = let m2 = LDecl.fresh_id hyps "&m" in - let q1 = Fsubst.f_subst_mem mright m2 q1 in - let q2 = Fsubst.f_subst_mem mleft m2 q2 in - f_forall_mems [poml;(m2,pomt);pomr] (f_imps [q1;q2] q) in + assert (q.ml = q1.ml && q.mr = q2.mr); + let q1 = (EcSubst.ts_inv_rebind_right q1 m2).inv in + let q2 = (EcSubst.ts_inv_rebind_left q2 m2).inv in + f_forall_mems [poml;(m2,pomt);pomr] (f_imps [q1;q2] q.inv) in (cond1, cond2) (* ------------------------------------------------------------------ *) @@ -43,21 +46,11 @@ module Low = struct let m1, m3 = es.es_ml, es.es_mr in let cond1, cond2 = transitivity_side_cond hyps - m1 m3 m1 m3 es.es_pr es.es_po p1 q1 mt p2 q2 in + m1 m3 m1 m3 (es_pr es) (es_po es) p1 q1 mt p2 q2 in let cond3 = - f_equivS_r { es with - es_mr = (mright,mt); - es_sr = c2; - es_pr = p1; - es_po = q1; - } in + f_equivS (snd es.es_ml) mt p1 es.es_sl c2 q1 in let cond4 = - f_equivS_r { es with - es_ml = (mleft, mt); - es_sl = c2; - es_pr = p2; - es_po = q2; - } in + f_equivS mt (snd es.es_mr) p2 c2 es.es_sr q2 in FApi.xmutate1 tc `Trans [cond1; cond2; cond3; cond4] @@ -65,12 +58,13 @@ module Low = struct let t_equivF_trans_r f (p1, q1) (p2, q2) tc = let env, hyps, _ = FApi.tc1_eflat tc in let ef = tc1_as_equivF tc in - let (prml, prmr), (poml, pomr) = Fun.equivF_memenv ef.ef_fl ef.ef_fr env in - let (_, pomt) = snd (Fun.hoareF_memenv f env) in + let ml, mr = ef.ef_ml, ef.ef_mr in + let (prml, prmr), (poml, pomr) = Fun.equivF_memenv ml mr ef.ef_fl ef.ef_fr env in + let (_, pomt) = snd (Fun.hoareF_memenv p1.ml f env) in let cond1, cond2 = transitivity_side_cond hyps prml prmr poml pomr - ef.ef_pr ef.ef_po p1 q1 pomt p2 q2 in + (ef_pr ef) (ef_po ef) p1 q1 pomt p2 q2 in let cond3 = f_equivF p1 ef.ef_fl f q1 in let cond4 = f_equivF p2 f ef.ef_fr q2 in @@ -85,23 +79,33 @@ let t_equivF_trans = FApi.t_low3 "equiv-trans" Low.t_equivF_trans_r let t_equivS_trans_eq side s tc = let env = FApi.tc1_env tc in let es = tc1_as_equivS tc in - let c, m = match side with `Left -> es.es_sl, es.es_ml | `Right -> es.es_sr, es.es_mr in + let c, m, mem_pre = match side with + | `Left -> + let mem_pre_ss = EcFol.split_sided (fst es.es_ml) (es_pr es) in + let mem_pre = Option.map (fun mpre -> ss_inv_generalize_right mpre (fst es.es_mr)) mem_pre_ss in + es.es_sl, es.es_ml, mem_pre + | `Right -> + let mem_pre_ss = EcFol.split_sided (fst es.es_mr) (es_pr es) in + let mem_pre = Option.map (fun mpre -> ss_inv_generalize_left mpre (fst es.es_ml)) mem_pre_ss in + es.es_sr, es.es_mr, mem_pre in - let mem_pre = EcFol.split_sided (EcMemory.memory m) es.es_pr in let fv_pr = EcPV.PV.fv env (EcMemory.memory m) es.es_pr in let fv_po = EcPV.PV.fv env (fst m) es.es_po in let fv_r = EcPV.s_read env c in + let ml, mr = (fst es.es_ml), (fst es.es_mr) in let mk_eqs fv = let vfv, gfv = EcPV.PV.elements fv in - let veq = List.map (fun (x,ty) -> f_eq (f_pvar x ty mleft) (f_pvar x ty mright)) vfv in - let geq = List.map (fun mp -> f_eqglob mp mleft mp mright) gfv in - f_ands (veq @ geq) in + let xl x ty = ss_inv_generalize_right (f_pvar x ty ml) mr in + let xr x ty = ss_inv_generalize_left (f_pvar x ty mr) ml in + let veq = List.map (fun (x,ty) -> map_ts_inv2 f_eq (xl x ty) (xr x ty)) vfv in + let geq = List.map (fun mp -> ts_inv_eqglob mp ml mp mr) gfv in + map_ts_inv ~ml ~mr f_ands (veq @ geq) in let pre = mk_eqs (EcPV.PV.union (EcPV.PV.union fv_pr fv_po) fv_r) in - let pre = f_and pre (odfl f_true mem_pre) in + let pre = map_ts_inv2 f_and pre (odfl {ml=pre.ml;mr=pre.mr;inv=f_true} mem_pre) in let post = mk_eqs fv_po in let c1, c2 = - if side = `Left then (pre, post), (es.es_pr, es.es_po) - else (es.es_pr, es.es_po), (pre, post) + if side = `Left then (pre, post), (es_pr es, es_po es) + else (es_pr es, es_po es), (pre, post) in let exists_subtac (tc : tcenv1) = @@ -185,13 +189,20 @@ let process_trans_stmt tf s ?pat c tc = t_equivS_trans_eq s c tc | TFform (p1, q1, p2, q2) -> let p1, q1 = - let hyps = LDecl.push_all [es.es_ml; (mright, mt)] hyps in - TTC.pf_process_form !!tc hyps tbool p1, TTC.pf_process_form !!tc hyps tbool q1 + let ml, mr = fst es.es_ml, fst es.es_mr in + let hyps = LDecl.push_active_ts es.es_ml es.es_mr hyps in + let p1 = TTC.pf_process_form !!tc hyps tbool p1 in + let q1 = TTC.pf_process_form !!tc hyps tbool q1 in + {ml;mr;inv=p1}, {ml;mr;inv=q1} in let p2, q2 = - let hyps = LDecl.push_all [(mleft, mt); es.es_mr] hyps in - TTC.pf_process_form !!tc hyps tbool p2, TTC.pf_process_form !!tc hyps tbool q2 + let ml, mr = fst es.es_ml, fst es.es_mr in + let hyps = LDecl.push_active_ts es.es_ml es.es_mr hyps in + let p2 = TTC.pf_process_form !!tc hyps tbool p2 in + let q2 = TTC.pf_process_form !!tc hyps tbool q2 in + {ml;mr;inv=p2}, {ml;mr;inv=q2} in + t_equivS_trans (mt, c) (p1, q1) (p2, q2) tc (* -------------------------------------------------------------------- *) @@ -199,14 +210,14 @@ let process_trans_fun f p1 q1 p2 q2 tc = let env, hyps, _ = FApi.tc1_eflat tc in let ef = tc1_as_equivF tc in let f = EcTyping.trans_gamepath env f in - let (_, prmt), (_, pomt) = Fun.hoareF_memenv f env in - let (prml, prmr), (poml, pomr) = Fun.equivF_memenv ef.ef_fl ef.ef_fr env in + let (prml, prmr), (poml, pomr) = Fun.equivF_memenv ef.ef_ml ef.ef_mr ef.ef_fl ef.ef_fr env in let process ml mr fo = - TTC.pf_process_form !!tc (LDecl.push_all [ml; mr] hyps) tbool fo in - let p1 = process prml (mright, prmt) p1 in - let q1 = process poml (mright, pomt) q1 in - let p2 = process (mleft,prmt) prmr p2 in - let q2 = process (mleft,pomt) pomr q2 in + let inv = TTC.pf_process_form !!tc (LDecl.push_active_ts ml mr hyps) tbool fo in + {ml=fst ml;mr=fst mr;inv} in + let p1 = process prml prmr p1 in + let q1 = process poml pomr q1 in + let p2 = process prml prmr p2 in + let q2 = process poml pomr q2 in t_equivF_trans f (p1, q1) (p2, q2) tc (* -------------------------------------------------------------------- *) diff --git a/src/phl/ecPhlTrans.mli b/src/phl/ecPhlTrans.mli index f113703fe..847d2234e 100644 --- a/src/phl/ecPhlTrans.mli +++ b/src/phl/ecPhlTrans.mli @@ -22,14 +22,14 @@ open EcCoreGoal.FApi (* -------------------------------------------------------------------- *) val t_equivS_trans : EcMemory.memtype * EcModules.stmt - -> EcFol.form * EcFol.form - -> EcFol.form * EcFol.form + -> EcAst.ts_inv * EcAst.ts_inv + -> EcAst.ts_inv * EcAst.ts_inv -> EcCoreGoal.FApi.backward val t_equivF_trans : EcPath.xpath - -> EcFol.form * EcFol.form - -> EcFol.form * EcFol.form + -> EcAst.ts_inv * EcAst.ts_inv + -> EcAst.ts_inv * EcAst.ts_inv -> EcCoreGoal.FApi.backward (*---------------------------------------------------------------------------------------*) diff --git a/src/phl/ecPhlUpto.ml b/src/phl/ecPhlUpto.ml index 82a8dfa70..28895cdae 100644 --- a/src/phl/ecPhlUpto.ml +++ b/src/phl/ecPhlUpto.ml @@ -16,8 +16,8 @@ open EcCoreLib.CI_Real (* -------------------------------------------------------------------- *) (* Core tactic *) -let e_true = expr_of_form mhr f_true -let e_false = expr_of_form mhr f_false +let e_true = expr_of_form f_true +let e_false = expr_of_form f_false let is_lv_bad env bad x = match bad with @@ -207,16 +207,16 @@ let f_upto_init env bad f1 f2 = | _, _ -> false -let destr_bad f = - match destr_pvar f with - | (PVglob _ as bad, m) when EcIdent.id_equal m mhr -> bad +let destr_bad (f: ss_inv) = + match destr_pvar f.inv with + | (PVglob _ as bad, m) when EcIdent.id_equal m f.m -> bad | _ -> destr_error "" let destr_not_bad f = - destr_bad (destr_not f) + destr_bad (map_ss_inv1 destr_not f) let destr_event f = - let b = try snd (destr_and f) with DestrError _ -> f in + let b = try snd (map_ss_inv_destr2 destr_and f) with DestrError _ -> f in destr_not_bad b let t_uptobad_r tc = @@ -230,10 +230,10 @@ let t_uptobad_r tc = tc_error !!tc ~who:"byupto" "the initial memories should be equal"; if not (is_conv ~ri:full_red hyps pr1.pr_args pr2.pr_args) then tc_error !!tc ~who:"byupto" "the initial arguments should be equal"; - if not (is_conv ~ri:full_red hyps pr1.pr_event pr2.pr_event) then + if not (ss_inv_alpha_eq hyps pr1.pr_event pr2.pr_event) then tc_error !!tc ~who:"byupto" "the events should be equal"; let bad = - try destr_event pr1.pr_event + try destr_event (pr1.pr_event) with DestrError _ -> tc_error !!tc ~who:"byupto" "the event should have the form \"E /\ !bad\" or \"!bad\"" in @@ -293,29 +293,30 @@ let destr_sub f1 f2 = let fe1, fe2 = DestrReal.sub f1 in let fe1b, fe2b = DestrReal.sub f2 in let pre1, pre2, prb1 = t3_map destr_pr (fe1, fe2, fe1b) in - let e, fbad = destr_and prb1.pr_event in - let fnbad = f_not fbad in - let fenb = f_and e fnbad in - let fe1nb = f_pr_r {pre1 with pr_event = fenb } in - let fe2nb = f_pr_r {pre2 with pr_event = fenb } in + let e, fbad = map_ss_inv_destr2 destr_and prb1.pr_event in + let fnbad = map_ss_inv1 f_not fbad in + let fenb = map_ss_inv2 f_and e fnbad in + let fe1nb = f_pr pre1.pr_mem pre1.pr_fun pre1.pr_args fenb in + let fe2nb = f_pr pre2.pr_mem pre2.pr_fun pre2.pr_args fenb in fe1, fe1b, fe1nb, fe2, fe2b, fe2nb, fbad let destr_sub_maxr f1 f2 = let fe1, fe2 = DestrReal.sub f1 in let fe1b', fe2b' = destr_maxr f2 in let pre1, pre2, prb1_ = t3_map destr_pr (fe1, fe2, fe1b') in + let mpr = prb1_.pr_mem in let bad = - let b = try snd (destr_and prb1_.pr_event) with DestrError _ -> prb1_.pr_event in + let b = try snd (map_ss_inv_destr2 destr_and prb1_.pr_event) with DestrError _ -> prb1_.pr_event in destr_bad b in - let fbad = f_pvar bad tbool mhr in + let fbad = f_pvar bad tbool mpr in let e = pre1.pr_event in - let fnbad = f_not fbad in - let fenb = f_and e fnbad in - let feb = f_and e fbad in - let fe1b = f_pr_r { pre1 with pr_event = feb } in - let fe1nb = f_pr_r { pre1 with pr_event = fenb } in - let fe2b = f_pr_r { pre2 with pr_event = feb } in - let fe2nb = f_pr_r { pre2 with pr_event = fenb } in + let fnbad = map_ss_inv1 f_not fbad in + let fenb = map_ss_inv2 f_and e fnbad in + let feb = map_ss_inv2 f_and e fbad in + let fe1b = f_pr pre1.pr_mem pre1.pr_fun pre1.pr_args feb in + let fe1nb = f_pr pre1.pr_mem pre1.pr_fun pre1.pr_args fenb in + let fe2b = f_pr pre2.pr_mem pre2.pr_fun pre2.pr_args feb in + let fe2nb = f_pr pre2.pr_mem pre2.pr_fun pre2.pr_args fenb in fe1, fe1b, fe1nb, fe2, fe2b, fe2nb, fbad, fe1b', fe2b' let t_split_pr fbad = @@ -352,25 +353,26 @@ let process_uptobad tc = | SFop((o,_), [f1; f]) when EcPath.p_equal o p_real_le -> begin match sform_of_form f1 with | SFpr pr1 -> + let mpr = pr1.pr_mem in (* Pr[G1 : E] <= Pr[G2 : E [/\ !bad]] + Pr[G1: [E /\] bad] *) let f2, fb = DestrReal.add f in let pr2, e, bad = try let pr2, prb = t2_map destr_pr (f2, fb) in let bad = - try destr_bad prb.pr_event - with DestrError _ -> destr_bad (snd (destr_and prb.pr_event)) + try destr_bad (prb.pr_event) + with DestrError _ -> destr_bad (snd (map_ss_inv_destr2 destr_and prb.pr_event)) in let e = pr1.pr_event in pr2, e, bad with DestrError _ -> error_add tc in - let fbad = f_pvar bad tbool mhr in - let fnbad = f_not fbad in + let fbad = (f_pvar bad tbool mpr) in + let fnbad = map_ss_inv1 f_not fbad in let pr1b, pr1nb, pr2nb = - f_pr_r {pr1 with pr_event = f_and e fbad}, - f_pr_r {pr1 with pr_event = f_and e fnbad}, - f_pr_r {pr2 with pr_event = f_and e fnbad} in + f_pr pr1.pr_mem pr1.pr_fun pr1.pr_args (map_ss_inv2 f_and e fbad), + f_pr pr1.pr_mem pr1.pr_fun pr1.pr_args (map_ss_inv2 f_and e fnbad), + f_pr pr2.pr_mem pr2.pr_fun pr2.pr_args (map_ss_inv2 f_and e fnbad) in (t_apply_prept (`App (`UG upto_le, [`F f1; `F pr1b; `F pr1nb; diff --git a/src/phl/ecPhlWhile.ml b/src/phl/ecPhlWhile.ml index 093edb9e3..3f60df39c 100644 --- a/src/phl/ecPhlWhile.ml +++ b/src/phl/ecPhlWhile.ml @@ -5,6 +5,7 @@ open EcTypes open EcFol open EcModules open EcPV +open EcParsetree open EcCoreGoal open EcLowPhlGoal @@ -65,18 +66,19 @@ let t_hoare_while_r inv tc = let env = FApi.tc1_env tc in let hs = tc1_as_hoareS tc in let (e, c), s = tc1_last_while tc hs.hs_s in - let m = EcMemory.memory hs.hs_m in - let e = form_of_expr m e in + let (m, mt) = hs.hs_m in + let e = ss_inv_of_expr m e in (* the body preserves the invariant *) - let b_pre = f_and_simpl inv e in + let b_pre = map_ss_inv2 f_and_simpl inv e in let b_post = inv in - let b_concl = f_hoareS hs.hs_m b_pre c b_post in + let b_concl = f_hoareS mt b_pre c b_post in (* the wp of the while *) - let post = f_imps_simpl [f_not_simpl e; inv] hs.hs_po in + let f_imps_simpl' f = f_imps_simpl (List.tl f) (List.hd f) in + let post = map_ss_inv f_imps_simpl' [hs_po hs;map_ss_inv1 f_not_simpl e; inv] in let modi = s_write env c in - let post = generalize_mod env m modi post in - let post = f_and_simpl inv post in - let concl = f_hoareS_r { hs with hs_s = s; hs_po=post} in + let post = generalize_mod_ss_inv env modi post in + let post = map_ss_inv2 f_and_simpl inv post in + let concl = f_hoareS mt (hs_pr hs) s post in FApi.xmutate1 tc `While [b_concl; concl] @@ -90,24 +92,25 @@ let t_ehoare_while_core tc = let hs = tc1_as_ehoareS tc in let (e, c), s = tc1_last_while tc hs.ehs_s in check_single_stmt tc s; - let m = EcMemory.memory hs.ehs_m in - let e = form_of_expr m e in - if not (EcReduction.is_conv hyps hs.ehs_po (f_interp_ehoare_form (f_not e) hs.ehs_pr)) then + let (m, mt) = hs.ehs_m in + let e = ss_inv_of_expr m e in + if not (EcReduction.ss_inv_alpha_eq hyps (ehs_po hs) + (map_ss_inv2 f_interp_ehoare_form (map_ss_inv1 f_not e) (ehs_pr hs))) then tc_error !!tc "ehoare while rule: wrong post-condition"; (* the body preserves the invariant *) - let b_pre = f_interp_ehoare_form e hs.ehs_pr in - let b_concl = f_eHoareS hs.ehs_m b_pre c hs.ehs_pr in + let b_pre = map_ss_inv2 f_interp_ehoare_form e (ehs_pr hs) in + let b_concl = f_eHoareS mt b_pre c (ehs_pr hs) in FApi.xmutate1 tc `While [b_concl] let t_ehoare_while inv tc = let hs = tc1_as_ehoareS tc in let (e,_), _ = tc1_last_while tc hs.ehs_s in let m = EcMemory.memory hs.ehs_m in - let e = form_of_expr m e in + let e = ss_inv_of_expr m e in let tc = FApi.t_rotate `Left 1 (EcPhlApp.t_ehoare_app (0, `ByPos (List.length hs.ehs_s.s_node - 1)) inv tc) in FApi.t_sub - [(EcPhlConseq.t_ehoareS_conseq inv (f_interp_ehoare_form (f_not e) inv)) @+ + [(EcPhlConseq.t_ehoareS_conseq inv (map_ss_inv2 f_interp_ehoare_form (map_ss_inv1 f_not e) inv)) @+ [t_trivial; t_id; t_ehoare_while_core ]; @@ -119,29 +122,27 @@ let t_bdhoare_while_r inv vrnt tc = let env = FApi.tc1_env tc in let bhs = tc1_as_bdhoareS tc in let (e, c), s = tc1_last_while tc bhs.bhs_s in - let m = EcMemory.memory bhs.bhs_m in - let e = form_of_expr m e in + let (m, mt) = bhs.bhs_m in + let e = ss_inv_of_expr m e in (* the body preserves the invariant *) let k_id = EcIdent.create "z" in - let k = f_local k_id tint in - let vrnt_eq_k = f_eq vrnt k in - let vrnt_lt_k = f_int_lt vrnt k in - let b_pre = f_and_simpl (f_and_simpl inv e) vrnt_eq_k in - let b_post = f_and_simpl inv vrnt_lt_k in - let b_concl = f_bdHoareS_r - { bhs with - bhs_pr = b_pre; bhs_s = c; bhs_po = b_post; - bhs_cmp = FHeq ; bhs_bd = f_r1} - in + let k = {m;inv=f_local k_id tint} in + let vrnt_eq_k = map_ss_inv2 f_eq vrnt k in + let vrnt_lt_k = map_ss_inv2 f_int_lt vrnt k in + let b_pre = map_ss_inv2 f_and_simpl (map_ss_inv2 f_and_simpl inv e) vrnt_eq_k in + let b_post = map_ss_inv2 f_and_simpl inv vrnt_lt_k in + let b_concl = f_bdHoareS mt b_pre c b_post FHeq {m;inv=f_r1} in let b_concl = f_forall_simpl [(k_id,GTty tint)] b_concl in (* the wp of the while *) - let post = f_imps_simpl [f_not_simpl e; inv] bhs.bhs_po in - let term_condition = f_imps_simpl [inv;f_int_le vrnt f_i0] (f_not_simpl e) in - let post = f_and term_condition post in + let f_imps_simpl' f = f_imps_simpl (List.tl f) (List.hd f) in + let post = map_ss_inv f_imps_simpl' [bhs_po bhs; map_ss_inv1 f_not_simpl e; inv] in + let term_condition = map_ss_inv f_imps_simpl' + [map_ss_inv1 f_not_simpl e; inv;map_ss_inv2 f_int_le vrnt {m;inv=f_i0}] in + let post = map_ss_inv2 f_and term_condition post in let modi = s_write env c in - let post = generalize_mod env m modi post in - let post = f_and_simpl inv post in - let concl = f_bdHoareS_r { bhs with bhs_s = s; bhs_po=post} in + let post = generalize_mod_ss_inv env modi post in + let post = map_ss_inv2 f_and_simpl inv post in + let concl = f_bdHoareS mt (bhs_pr bhs) s post bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `While [b_concl; concl] @@ -154,13 +155,14 @@ let t_bdhoare_while_rev_r inv tc = if bhs.bhs_cmp <> FHle then tc_error !!tc "only judgments with an upper-bounded are supported"; - let b_pre = bhs.bhs_pr in - let b_post = bhs.bhs_po in + let b_pre = (bhs_pr bhs) in + let b_post = (bhs_po bhs) in let mem = bhs.bhs_m in - let bound = bhs.bhs_bd in + let (m, mt) = mem in + let bound = (bhs_bd bhs) in let (lp_guard_exp, lp_body), rem_s = tc1_last_while tc bhs.bhs_s in - let lp_guard = form_of_expr (EcMemory.memory mem) lp_guard_exp in + let lp_guard = ss_inv_of_expr (EcMemory.memory mem) lp_guard_exp in let w_u = while_info env lp_guard_exp lp_body in let w = EcEnv.LDecl.fresh_id hyps "w" in @@ -170,9 +172,9 @@ let t_bdhoare_while_rev_r inv tc = let body_concl = let while_s = EcModules.stmt [EcModules.i_abstract w] in let unfolded_while_s = EcModules.s_seq lp_body while_s in - let while_jgmt = f_bdHoareS_r {bhs with bhs_pr=inv ; bhs_s=while_s; } in - let unfolded_while_jgmt = f_bdHoareS_r - { bhs with bhs_pr = f_and inv lp_guard; bhs_s = unfolded_while_s; } + let while_jgmt = f_bdHoareS mt inv while_s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in + let unfolded_while_jgmt = f_bdHoareS + mt (map_ss_inv2 f_and inv lp_guard) unfolded_while_s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in f_imp while_jgmt unfolded_while_jgmt in @@ -180,12 +182,12 @@ let t_bdhoare_while_rev_r inv tc = (* 2. Sub-goal *) let rem_concl = let modi = s_write env lp_body in - let term_post = f_imp - (f_and inv (f_and (f_not lp_guard) b_post)) - (f_eq bound f_r1) in - let term_post = generalize_mod env (EcMemory.memory mem) modi term_post in - let term_post = f_and inv term_post in - f_hoareS mem b_pre rem_s term_post + let term_post = map_ss_inv2 f_imp + (map_ss_inv2 f_and inv (map_ss_inv2 f_and (map_ss_inv1 f_not lp_guard) b_post)) + (map_ss_inv2 f_eq bound {m;inv=f_r1}) in + let term_post = generalize_mod_ss_inv env modi term_post in + let term_post = map_ss_inv2 f_and inv term_post in + f_hoareS mt b_pre rem_s term_post in FApi.xmutate1_hyps tc `While [(hyps', body_concl); (hyps, rem_concl)] @@ -193,7 +195,7 @@ let t_bdhoare_while_rev_r inv tc = (* -------------------------------------------------------------------- *) (* Rule for = or >= *) -let t_bdhoare_while_rev_geq_r inv vrnt k eps tc = +let t_bdhoare_while_rev_geq_r inv vrnt k (eps: ss_inv) tc = let env, hyps, _ = FApi.tc1_eflat tc in let bhs = tc1_as_bdhoareS tc in @@ -201,71 +203,70 @@ let t_bdhoare_while_rev_geq_r inv vrnt k eps tc = if bhs.bhs_cmp = FHle then tc_error !!tc "only judgments with an lower/eq-bounded are supported"; - let b_pre = bhs.bhs_pr in - let b_post = bhs.bhs_po in + let b_pre = bhs_pr bhs in + let b_post = bhs_po bhs in let mem = bhs.bhs_m in + let (m, mt) = mem in let (lp_guard_exp, lp_body), rem_s = tc1_last_while tc bhs.bhs_s in - if not (PV.indep env (s_write env lp_body) (PV.fv env (EcMemory.memory mem) eps)) then + if not (PV.indep env (s_write env lp_body) (PV.fv env (EcMemory.memory mem) eps.inv)) then tc_error !!tc "The variant decreasing rate lower-bound cannot " "depend on variables written by the loop body"; check_single_stmt tc rem_s; - let lp_guard = form_of_expr (EcMemory.memory mem) lp_guard_exp in - let bound = bhs.bhs_bd in + let lp_guard = ss_inv_of_expr m lp_guard_exp in + let bound = bhs_bd bhs in let modi = s_write env lp_body in (* 1. Pre-invariant *) - let pre_inv_concl = f_forall_mems [mem] (f_imp b_pre inv) in + let pre_inv_concl = EcSubst.f_forall_mems_ss_inv mem (map_ss_inv2 f_imp b_pre inv) in (* 2. Pre-bound *) let pre_bound_concl = - let term_post = [b_pre; f_not lp_guard] in + let term_post = [b_pre; map_ss_inv1 f_not lp_guard] in let concl = if bhs.bhs_cmp = FHeq then - f_eq bound (f_if b_post f_r1 f_r0) - else f_imp (f_not b_post) (f_eq bound f_r0) in - let term_post = f_imps term_post concl in - let term_post = generalize_mod env (EcMemory.memory mem) modi term_post in - f_forall_mems [mem] term_post + map_ss_inv2 f_eq bound (map_ss_inv3 f_if b_post {m;inv=f_r1} {m;inv=f_r0}) + else map_ss_inv2 f_imp (map_ss_inv1 f_not b_post) (map_ss_inv2 f_eq bound {m;inv=f_r0}) in + let f_imps' f = f_imps (List.tl f) (List.hd f) in + let term_post = map_ss_inv f_imps' (concl::term_post) in + let term_post = generalize_mod_ss_inv env modi term_post in + EcSubst.f_forall_mems_ss_inv mem term_post in (* 3. Term-invariant *) let inv_term_concl = - let concl = f_imp (f_int_le vrnt f_i0) (f_not lp_guard) in - let concl = f_and (f_int_le vrnt k) concl in - let concl = f_imp inv concl in - f_forall_mems [mem] (generalize_mod env (EcMemory.memory mem) modi concl) + let concl = map_ss_inv2 f_imp (map_ss_inv2 f_int_le vrnt {m;inv=f_i0}) (map_ss_inv1 f_not lp_guard) in + let concl = map_ss_inv2 f_and (map_ss_inv2 f_int_le vrnt k) concl in + let concl = map_ss_inv2 f_imp inv concl in + EcSubst.f_forall_mems_ss_inv mem (generalize_mod_ss_inv env modi concl) in (* 4. Vrnt conclusion *) let vrnt_concl = let k_id = EcIdent.create "z" in - let k = f_local k_id tint in - let vrnt_eq_k = f_eq vrnt k in - let vrnt_lt_k = f_int_lt vrnt k in + let k = {m;inv=f_local k_id tint} in + let vrnt_eq_k = map_ss_inv2 f_eq vrnt k in + let vrnt_lt_k = map_ss_inv2 f_int_lt vrnt k in f_and - (f_forall_mems [mem] (f_imp inv (f_real_lt f_r0 eps))) + (EcSubst.f_forall_mems_ss_inv mem (map_ss_inv2 f_imp inv + (map_ss_inv2 f_real_lt {m;inv=f_r0} eps))) (f_forall_simpl [(k_id,GTty tint)] - (f_bdHoareS_r { bhs with - bhs_pr = f_ands [inv;lp_guard;vrnt_eq_k]; - bhs_po = vrnt_lt_k; - bhs_s = lp_body; - bhs_cmp = FHge; - bhs_bd = eps })) + (f_bdHoareS + mt + (map_ss_inv f_ands [inv;lp_guard;vrnt_eq_k]) + lp_body + vrnt_lt_k + FHge + eps)) in (* 5. Out invariant *) let inv_concl = - f_bdHoareS_r { bhs with - bhs_pr = f_and inv lp_guard; - bhs_po = inv; - bhs_s = lp_body; - bhs_cmp = FHeq; - bhs_bd = f_r1; } + f_bdHoareS mt (map_ss_inv2 f_and inv lp_guard) lp_body inv FHeq {m;inv=f_r1} in (* 6. Out body *) @@ -277,9 +278,9 @@ let t_bdhoare_while_rev_geq_r inv vrnt k eps tc = let while_s1 = EcModules.stmt [EcModules.i_abstract w] in let unfolded_while_s = EcModules.s_seq lp_body while_s1 in - let while_jgmt = f_bdHoareS_r { bhs with bhs_pr=b_pre; bhs_s=while_s1; } in - let unfolded_while_jgmt = f_bdHoareS_r - { bhs with bhs_pr=f_and b_pre lp_guard; bhs_s=unfolded_while_s; } + let while_jgmt = f_bdHoareS mt b_pre while_s1 (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in + let unfolded_while_jgmt = f_bdHoareS + mt (map_ss_inv2 f_and b_pre lp_guard) unfolded_while_s (bhs_po bhs) bhs.bhs_cmp (bhs_bd bhs) in f_imp while_jgmt unfolded_while_jgmt in @@ -296,45 +297,48 @@ let t_bdhoare_while_rev_geq_r inv vrnt k eps tc = let t_equiv_while_disj_r side vrnt inv tc = let env = FApi.tc1_env tc in let es = tc1_as_equivS tc in + let ss_inv_generalize_other f = + match side with + | `Left -> ss_inv_generalize_right f (fst es.es_mr) + | `Right -> ss_inv_generalize_left f (fst es.es_ml) in + let ts_inv_lower_side2 = sideif side ts_inv_lower_left2 ts_inv_lower_right2 in + let generalize_mod_side = sideif side generalize_mod_left generalize_mod_right in let s, m_side, m_other = match side with | `Left -> es.es_sl, es.es_ml, es.es_mr | `Right -> es.es_sr, es.es_mr, es.es_ml in + let (ml, mr) = (fst es.es_ml, fst es.es_mr) in let (e, c), s = tc1_last_while tc s in - let e = form_of_expr (EcMemory.memory m_side) e in + let e = ss_inv_of_expr (EcMemory.memory m_side) e in + let e = ss_inv_generalize_other e in (* 1. The body preserves the invariant and the variant decreases. *) let k_id = EcIdent.create "z" in - let k = f_local k_id tint in + let k = {ml;mr;inv=f_local k_id tint} in - let vrnt_eq_k = f_eq vrnt k in - let vrnt_lt_k = f_int_lt vrnt k in + let vrnt_eq_k = map_ts_inv2 f_eq vrnt k in + let vrnt_lt_k = map_ts_inv2 f_int_lt vrnt k in - let m_other' = (EcIdent.create "&m", EcMemory.memtype m_other) in - - let smem = Fsubst.f_subst_id in - let smem = Fsubst.f_bind_mem smem (EcMemory.memory m_side ) mhr in - let smem = Fsubst.f_bind_mem smem (EcMemory.memory m_other) (EcMemory.memory m_other') in - - let b_pre = f_and_simpl (f_and_simpl inv e) vrnt_eq_k in - let b_pre = Fsubst.f_subst smem b_pre in - let b_post = f_and_simpl inv vrnt_lt_k in - let b_post = Fsubst.f_subst smem b_post in - let b_concl = f_bdHoareS (mhr, EcMemory.memtype m_side) b_pre c b_post FHeq f_r1 in - let b_concl = f_forall_simpl [(k_id,GTty tint)] b_concl in - let b_concl = f_forall_mems [m_other'] b_concl in + let b_pre = map_ts_inv2 f_and_simpl (map_ts_inv2 f_and_simpl inv e) vrnt_eq_k in + let b_post = map_ts_inv2 f_and_simpl inv vrnt_lt_k in + let b_concl = ts_inv_lower_side2 (fun pr po -> + f_bdHoareS (snd m_side) pr c po FHeq {m=(fst m_side);inv=f_r1}) b_pre b_post in + let b_concl = map_ss_inv1 (f_forall_simpl [(k_id,GTty tint)]) b_concl in + let b_concl = EcSubst.f_forall_mems_ss_inv m_other b_concl in (* 2. WP of the while *) - let post = f_imps_simpl [f_not_simpl e; inv] es.es_po in - let term_condition = f_imps_simpl [inv;f_int_le vrnt f_i0] (f_not_simpl e) in - let post = f_and term_condition post in + let f_imps_simpl' fl = f_imps_simpl (List.tl fl) (List.hd fl) in + let post = map_ts_inv f_imps_simpl' [es_po es; map_ts_inv1 f_not_simpl e; inv] in + let term_condition = map_ts_inv + f_imps_simpl' [map_ts_inv1 f_not_simpl e; inv;map_ts_inv2 f_int_le vrnt {ml;mr;inv=f_i0}] in + let post = map_ts_inv2 f_and term_condition post in let modi = s_write env c in - let post = generalize_mod env (EcMemory.memory m_side) modi post in - let post = f_and_simpl inv post in + let post = generalize_mod_side env modi post in + let post = map_ts_inv2 f_and_simpl inv post in let concl = match side with - | `Left -> f_equivS_r { es with es_sl = s; es_po=post; } - | `Right -> f_equivS_r { es with es_sr = s; es_po=post; } + | `Left -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) s es.es_sr post + | `Right -> f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) es.es_sl s post in FApi.xmutate1 tc `While [b_concl; concl] @@ -345,25 +349,26 @@ let t_equiv_while_r inv tc = let es = tc1_as_equivS tc in let (el, cl), sl = tc1_last_while tc es.es_sl in let (er, cr), sr = tc1_last_while tc es.es_sr in - let ml = EcMemory.memory es.es_ml in - let mr = EcMemory.memory es.es_mr in - let el = form_of_expr ml el in - let er = form_of_expr mr er in - let sync_cond = f_iff_simpl el er in + let ml, mr = fst es.es_ml, fst es.es_mr in + let el = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let er = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in + let sync_cond = map_ts_inv2 f_iff_simpl el er in (* 1. The body preserves the invariant *) - let b_pre = f_ands_simpl [inv; el] er in - let b_post = f_and_simpl inv sync_cond in - let b_concl = f_equivS es.es_ml es.es_mr b_pre cl cr b_post in + let f_ands_simpl' f = f_ands_simpl (List.tl f) (List.hd f) in + let b_pre = map_ts_inv f_ands_simpl' [er; inv; el] in + let b_post = map_ts_inv2 f_and_simpl inv sync_cond in + let b_concl = f_equivS (snd es.es_ml) (snd es.es_mr) b_pre cl cr b_post in (* 2. WP of the while *) - let post = f_imps_simpl [f_not_simpl el;f_not_simpl er; inv] es.es_po in + let f_imps_simpl' f = f_imps_simpl (List.tl f) (List.hd f) in + let post = map_ts_inv f_imps_simpl' [es_po es; + map_ts_inv1 f_not_simpl el; map_ts_inv1 f_not_simpl er; inv] in let modil = s_write env cl in let modir = s_write env cr in - let post = generalize_mod env mr modir post in - let post = generalize_mod env ml modil post in - let post = f_and_simpl b_post post in - let concl = f_equivS_r { es with es_sl = sl; es_sr = sr; es_po = post; } in + let post = generalize_mod_ts_inv env modil modir post in + let post = map_ts_inv2 f_and_simpl b_post post in + let concl = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl sr post in FApi.xmutate1 tc `While [b_concl; concl] @@ -529,60 +534,54 @@ let process_async_while (winfos : EP.async_while_info) tc = let p1 = TTC.tc1_process_prhl_formula tc p1 in let f1 = TTC.tc1_process_prhl_form_opt tc None f1 in let f2 = TTC.tc1_process_prhl_form_opt tc None f2 in - let t1 = TTC.tc1_process_Xhl_exp tc (Some `Left ) (Some (tfun f1.f_ty tbool)) t1 in - let t2 = TTC.tc1_process_Xhl_exp tc (Some `Right) (Some (tfun f2.f_ty tbool)) t2 in - let ft1 = form_of_expr ml t1 in - let ft2 = form_of_expr mr t2 in - let fe1 = form_of_expr ml el in - let fe2 = form_of_expr mr er in - let fe = f_or fe1 fe2 in - - let cond1 = f_forall_mems [evs.es_ml; evs.es_mr] - (f_imps [inv; fe; p0] (f_ands [fe1; fe2; - f_app ft1 [f1] tbool; - f_app ft2 [f2] tbool])) in - - let cond2 = f_forall_mems [evs.es_ml; evs.es_mr] - (f_imps [inv; fe; f_not p0; p1] fe1) in - - let cond3 = f_forall_mems [evs.es_ml; evs.es_mr] - (f_imps [inv; fe; f_not p0; f_not p1] fe2) in + let t1 = TTC.tc1_process_Xhl_exp tc (Some `Left ) (Some (tfun f1.inv.f_ty tbool)) t1 in + let t2 = TTC.tc1_process_Xhl_exp tc (Some `Right) (Some (tfun f2.inv.f_ty tbool)) t2 in + let ft1 = ss_inv_generalize_right (ss_inv_of_expr ml t1) mr in + let ft2 = ss_inv_generalize_left (ss_inv_of_expr mr t2) ml in + let fe1 = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let fe2 = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in + let fe = map_ts_inv2 f_or fe1 fe2 in + let f_app' f = f_app (List.hd f) (List.tl f) tbool in + let f_imps' f = f_imps (List.tl f) (List.hd f) in + let cond1 = EcSubst.f_forall_mems_ts_inv evs.es_ml evs.es_mr + (map_ts_inv f_imps' [map_ts_inv f_ands [fe1; fe2; + map_ts_inv f_app' [ft1; f1]; + map_ts_inv f_app' [ft2; f2]]; + inv; fe; p0]) in + + let cond2 = EcSubst.f_forall_mems_ts_inv evs.es_ml evs.es_mr + (map_ts_inv f_imps' [fe1; inv; fe; map_ts_inv1 f_not p0; p1]) in + + let cond3 = EcSubst.f_forall_mems_ts_inv evs.es_ml evs.es_mr + (map_ts_inv f_imps' [fe2; inv; fe; map_ts_inv1 f_not p0; map_ts_inv1 f_not p1]) in let xwh = let v1, v2 = as_seq2 (EcEnv.LDecl.fresh_ids hyps ["v1_"; "v2_"]) in - let fv1 = f_local v1 f1.f_ty in - let fv2 = f_local v2 f2.f_ty in - let ev1 = e_local v1 f1.f_ty in - let ev2 = e_local v2 f2.f_ty in - let eq1 = f_eq fv1 f1 and eq2 = f_eq fv2 f2 in - let pr = f_ands [inv; fe; p0; eq1; eq2] in + let fv1 = {ml;mr;inv=f_local v1 f1.inv.f_ty} in + let fv2 = {ml;mr;inv=f_local v2 f2.inv.f_ty} in + let ev1 = e_local v1 f1.inv.f_ty in + let ev2 = e_local v2 f2.inv.f_ty in + let eq1 = map_ts_inv2 f_eq fv1 f1 and eq2 = map_ts_inv2 f_eq fv2 f2 in + let pr = map_ts_inv f_ands [inv; fe; p0; eq1; eq2] in let po = inv in let wl = s_while (e_and el (e_app t1 [ev1] tbool), cl) in let wr = s_while (e_and er (e_app t2 [ev2] tbool), cr) in - EcFol.f_forall [(v1, GTty f1.f_ty); (v2, GTty f2.f_ty)] - (f_equivS evs.es_ml evs.es_mr pr wl wr po) + EcFol.f_forall [(v1, GTty f1.inv.f_ty); (v2, GTty f2.inv.f_ty)] + (f_equivS (snd evs.es_ml) (snd evs.es_mr) pr wl wr po) in let hr1, hr2 = let hr1 = - let subst = Fsubst.f_bind_mem Fsubst.f_subst_id ml mhr in - let inv = Fsubst.f_subst subst inv in - let p0 = Fsubst.f_subst subst p0 in - let p1 = Fsubst.f_subst subst p1 in - - let pre = f_ands [inv; form_of_expr mhr el; f_not p0; p1] in - f_forall_mems [evs.es_mr] - (f_hoareS (mhr, EcMemory.memtype evs.es_ml) pre cl inv) + let el = ss_inv_generalize_right (ss_inv_of_expr ml el) mr in + let pre = map_ts_inv f_ands [inv; el ; map_ts_inv1 f_not p0; p1] in + EcSubst.f_forall_mems_ss_inv evs.es_mr + (ts_inv_lower_left2 (fun pr po -> f_hoareS (snd evs.es_ml) pr cl po) pre inv) and hr2 = - let subst = Fsubst.f_bind_mem Fsubst.f_subst_id mr mhr in - let inv = Fsubst.f_subst subst inv in - let p0 = Fsubst.f_subst subst p0 in - let p1 = Fsubst.f_subst subst p1 in - - let pre = f_ands [inv; form_of_expr mhr er; f_not p0; f_not p1] in - f_forall_mems [evs.es_ml] - (f_hoareS (mhr, EcMemory.memtype evs.es_mr) pre cr inv) + let er = ss_inv_generalize_left (ss_inv_of_expr mr er) ml in + let pre = map_ts_inv f_ands [inv; er; map_ts_inv1 f_not p0; map_ts_inv1 f_not p1] in + EcSubst.f_forall_mems_ss_inv evs.es_ml + (ts_inv_lower_right2 (fun pr po -> f_hoareS (snd evs.es_mr) pr cr po) pre inv) in (hr1, hr2) in @@ -590,16 +589,16 @@ let process_async_while (winfos : EP.async_while_info) tc = let xhyps = let mtypes = Mid.of_list [evs.es_ml; evs.es_mr] in - fun m fp -> - let fp = + fun m (fp: ss_inv): (_ * form) -> + let fp: form = Mid.fold (fun mh pvs fp -> let mty = Mid.find_opt mh mtypes in let fp = EcPV.Mnpv.fold (fun pv (x, ty) fp -> - f_let1 x (f_pvar pv ty mh) fp) + (f_let1 x) (f_pvar pv ty mh).inv fp) (EcPV.PVMap.raw pvs) fp in f_forall_mems [mh, oget mty] fp) - m fp + m fp.inv and cnt = Mid.fold (fun _ pvs i -> i + 1 + EcPV.Mnpv.cardinal (EcPV.PVMap.raw pvs)) @@ -610,22 +609,18 @@ let process_async_while (winfos : EP.async_while_info) tc = let (c1, ll1), (c2, ll2) = try let ll1 = - let subst = Fsubst.f_bind_mem Fsubst.f_subst_id ml mhr in - let inv = Fsubst.f_subst subst inv in - let test = f_ands [fe1; f_not p0; p1] in + let test = f_ands [fe1.inv; f_not p0.inv; p1.inv] in let test, m = ASyncWhile.form_of_expr env (EcMemory.memory evs.es_mr) ml test in let c = s_while (test, cl) in xhyps m - (f_bdHoareS (mhr, EcMemory.memtype evs.es_ml) inv c f_true FHeq f_r1) + (ts_inv_lower_left3 (fun inv f_tr f_r1 -> f_bdHoareS (snd evs.es_ml) inv c f_tr FHeq f_r1) inv {ml;mr;inv=f_true} {ml;mr;inv=f_r1}) and ll2 = - let subst = Fsubst.f_bind_mem Fsubst.f_subst_id mr mhr in - let inv = Fsubst.f_subst subst inv in - let test = f_ands [fe1; f_not p0; f_not p1] in + let test = f_ands [fe1.inv; f_not p0.inv; f_not p1.inv] in let test, m = ASyncWhile.form_of_expr env (EcMemory.memory evs.es_ml) mr test in let c = s_while (test, cr) in xhyps m - (f_bdHoareS (mhr, EcMemory.memtype evs.es_mr) inv c f_true FHeq f_r1) + (ts_inv_lower_right3 (fun inv f_tr f_r1 -> f_bdHoareS (snd evs.es_mr) inv c f_tr FHeq f_r1) inv {ml;mr;inv=f_true} {ml;mr;inv=f_r1}) in (ll1, ll2) @@ -635,12 +630,12 @@ let process_async_while (winfos : EP.async_while_info) tc = in let concl = - let post = f_imps [f_not fe1; f_not fe2; inv] evs.es_po in + let f_imps' f = f_imps (List.tl f) (List.hd f) in + let post = map_ts_inv f_imps' [es_po evs; map_ts_inv1 f_not fe1; map_ts_inv1 f_not fe2; inv] in let modil = s_write env cl in let modir = s_write env cr in - let post = generalize_mod env mr modir post in - let post = generalize_mod env ml modil post in - f_equivS_r { evs with es_sl = sl; es_sr = sr; es_po = f_and inv post; } in + let post = generalize_mod_ts_inv env modil modir post in + f_equivS (snd evs.es_ml) (snd evs.es_mr) (es_pr evs) sl sr (map_ts_inv2 f_and inv post) in FApi.t_onfsub (function | 6 -> Some (EcLowGoal.t_intros_n c1) diff --git a/src/phl/ecPhlWhile.mli b/src/phl/ecPhlWhile.mli index f4c01f3ad..8c89014ca 100644 --- a/src/phl/ecPhlWhile.mli +++ b/src/phl/ecPhlWhile.mli @@ -1,13 +1,13 @@ (* -------------------------------------------------------------------- *) open EcParsetree -open EcFol open EcCoreGoal.FApi +open EcAst (* -------------------------------------------------------------------- *) -val t_hoare_while : form -> backward -val t_bdhoare_while : form -> form -> backward -val t_equiv_while_disj : side -> form -> form -> backward -val t_equiv_while : form -> backward +val t_hoare_while : ss_inv -> backward +val t_bdhoare_while : ss_inv -> ss_inv -> backward +val t_equiv_while_disj : side -> ts_inv -> ts_inv -> backward +val t_equiv_while : ts_inv -> backward (* -------------------------------------------------------------------- *) val process_while : oside -> while_info -> backward diff --git a/src/phl/ecPhlWp.ml b/src/phl/ecPhlWp.ml index 9c7553f56..18ad965ce 100644 --- a/src/phl/ecPhlWp.ml +++ b/src/phl/ecPhlWp.ml @@ -13,7 +13,7 @@ module LowInternal = struct let wp_asgn_aux c_pre memenv lv e (lets, f) = let m = EcMemory.memory memenv in - let let1 = lv_subst ?c_pre m lv (form_of_expr m e) in + let let1 = lv_subst ?c_pre m lv (ss_inv_of_expr m e).inv in (let1::lets, f) let rec wp_stmt @@ -41,7 +41,7 @@ module LowInternal = struct let post1 = mk_let_of_lv_substs env letsf1 in let post2 = mk_let_of_lv_substs env letsf2 in let m = EcMemory.memory memenv in - let post = f_if (form_of_expr m e) post1 post2 in + let post = f_if (ss_inv_of_expr m e).inv post1 post2 in let post = f_and_simpl (odfl f_true c_pre) post in ([], post) end else raise No_wp @@ -66,14 +66,14 @@ module LowInternal = struct let post = f_and_simpl (odfl f_true c_pre) - (f_match (form_of_expr m e) pbs EcTypes.tbool) in + (f_match (ss_inv_of_expr m e).inv pbs EcTypes.tbool) in ([],post) end | Sassert e when onesided -> - let phi = form_of_expr (EcMemory.memory memenv) e in + let phi = ss_inv_of_expr (EcMemory.memory memenv) e in let lets, f = letsf in - (lets, EcFol.f_and_simpl phi f) + (lets, EcFol.f_and_simpl phi.inv f) | _ -> raise No_wp @@ -97,7 +97,7 @@ module LowInternal = struct let x_id = EcIdent.create (symbol_of_lv lv) in let x = f_local x_id ty_distr in let m = EcMemory.memory memenv in - let distr = EcFol.form_of_expr m distr in + let distr = (EcFol.ss_inv_of_expr m distr).inv in let let1 = lv_subst ?c_pre:None m lv x in let lets = let1 :: lets in let f = mk_let_of_lv_substs env (lets,f) in @@ -111,7 +111,7 @@ module LowInternal = struct let f1 = mk_let_of_lv_substs env (lets1,f1) in let f2 = mk_let_of_lv_substs env (lets2,f2) in let m = EcMemory.memory memenv in - let e = form_of_expr m e in + let e = (ss_inv_of_expr m e).inv in let f = f_if e f1 f2 in ([], f) end else raise No_wp @@ -148,7 +148,8 @@ module TacInternal = struct wp ~uselet ~onesided:true env hs.hs_m s_wp hs.hs_po in check_wp_progress tc i hs.hs_s s_wp; let s = EcModules.stmt (s_hd @ s_wp) in - let concl = f_hoareS_r { hs with hs_s = s; hs_po = post} in + let m = fst hs.hs_m in + let concl = f_hoareS (snd hs.hs_m) {m;inv=hs.hs_pr} s {m;inv=post} in FApi.xmutate1 tc `Wp [concl] let t_ehoare_wp ?(uselet=true) i tc = @@ -159,7 +160,8 @@ module TacInternal = struct let (s_wp, post) = ewp ~uselet env hs.ehs_m s_wp hs.ehs_po in check_wp_progress tc i hs.ehs_s s_wp; let s = EcModules.stmt (s_hd @ s_wp) in - let concl = f_eHoareS_r { hs with ehs_s = s; ehs_po = post} in + let m = fst hs.ehs_m in + let concl = f_eHoareS (snd hs.ehs_m) (ehs_pr hs) s {m;inv=post} in FApi.xmutate1 tc `Wp [concl] let t_bdhoare_wp ?(uselet=true) i tc = @@ -170,7 +172,8 @@ module TacInternal = struct let s_wp,post = wp ~uselet env bhs.bhs_m s_wp bhs.bhs_po in check_wp_progress tc i bhs.bhs_s s_wp; let s = EcModules.stmt (s_hd @ s_wp) in - let concl = f_bdHoareS_r { bhs with bhs_s = s; bhs_po = post} in + let m = fst bhs.bhs_m in + let concl = f_bdHoareS (snd bhs.bhs_m) (bhs_pr bhs) s {m;inv=post} bhs.bhs_cmp (bhs_bd bhs) in FApi.xmutate1 tc `Wp [concl] let t_equiv_wp ?(uselet=true) ij tc = @@ -188,7 +191,8 @@ module TacInternal = struct check_wp_progress tc j es.es_sr s_wpr; let sl = EcModules.stmt (s_hdl @ s_wpl) in let sr = EcModules.stmt (s_hdr @ s_wpr) in - let concl = f_equivS_r {es with es_sl = sl; es_sr=sr; es_po = post} in + let ml, mr = (fst es.es_ml), (fst es.es_mr) in + let concl = f_equivS (snd es.es_ml) (snd es.es_mr) (es_pr es) sl sr {ml;mr;inv=post} in FApi.xmutate1 tc `Wp [concl] end