(* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) open Sledge open Fol let%test_module _ = ( module struct let () = Trace.init ~margin:68 ~config:(Result.get_ok (Trace.parse "+Solver.infer_frame")) () (* let () = * Trace.init ~margin:160 * ~config: * (Result.get_ok (Trace.parse "+Solver.infer_frame+Solver.excise")) * () *) [@@@warning "-32"] let infer_frame p xs q = Solver.infer_frame p (Var.Set.of_list xs) q |> (ignore : Sh.t option -> _) let check_frame p xs q = Solver.infer_frame p (Var.Set.of_list xs) q |> fun r -> assert (Option.is_some r) let ( ! ) i = Term.integer (Z.of_int i) let ( + ) = Term.add let ( - ) = Term.sub let ( * ) i e = Term.mulq (Q.of_int i) e let wrt = Var.Set.empty let a_, wrt = Var.fresh "a" ~wrt let a2_, wrt = Var.fresh "a" ~wrt let a3_, wrt = Var.fresh "a" ~wrt let b_, wrt = Var.fresh "b" ~wrt let k_, wrt = Var.fresh "k" ~wrt let l_, wrt = Var.fresh "l" ~wrt let l2_, wrt = Var.fresh "l" ~wrt let m_, wrt = Var.fresh "m" ~wrt let n_, _ = Var.fresh "n" ~wrt let a = Term.var a_ let a2 = Term.var a2_ let a3 = Term.var a3_ let b = Term.var b_ let k = Term.var k_ let l = Term.var l_ let l2 = Term.var l2_ let m = Term.var m_ let n = Term.var n_ let%expect_test _ = check_frame Sh.emp [] Sh.emp ; [%expect {| ( infer_frame: 0 emp \- emp ) infer_frame: emp |}] let%expect_test _ = check_frame (Sh.false_ Var.Set.empty) [] Sh.emp ; [%expect {| ( infer_frame: 1 false \- emp ) infer_frame: false |}] let%expect_test _ = check_frame Sh.emp [n_; m_] (Sh.and_ (Formula.eq m n) Sh.emp) ; [%expect {| ( infer_frame: 2 emp \- ∃ %m_8, %n_9 . %m_8 = %n_9 ∧ emp ) infer_frame: %m_8 = %n_9 ∧ emp |}] let%expect_test _ = check_frame (Sh.seg {loc= l; bas= b; len= m; siz= n; cnt= a}) [] Sh.emp ; [%expect {| ( infer_frame: 3 %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ \- emp ) infer_frame: %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ |}] let%expect_test _ = check_frame (Sh.seg {loc= l; bas= b; len= m; siz= n; cnt= a}) [] (Sh.seg {loc= l; bas= b; len= m; siz= n; cnt= a}) ; [%expect {| ( infer_frame: 4 %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ \- %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ ) infer_frame: emp |}] let%expect_test _ = let common = Sh.seg {loc= l2; bas= b; len= !10; siz= !10; cnt= a2} in let seg1 = Sh.seg {loc= l; bas= b; len= !10; siz= !10; cnt= a} in let minued = Sh.star common seg1 in let subtrahend = Sh.and_ (Formula.eq m n) (Sh.exists (Var.Set.of_list [m_]) (Sh.extend_us (Var.Set.of_list [m_]) common)) in infer_frame minued [n_; m_] subtrahend ; [%expect {| ( infer_frame: 5 %l_6 -[ %b_4, 10 )-> ⟨10,%a_1⟩ * %l_7 -[ %b_4, 10 )-> ⟨10,%a_2⟩ \- ∃ %m_8, %n_9 . ∃ %m_10 . %m_8 = %n_9 ∧ %l_7 -[ %b_4, 10 )-> ⟨10,%a_2⟩ ) infer_frame: ∃ %m_10 . %m_8 = %n_9 ∧ %l_6 -[ %b_4, 10 )-> ⟨10,%a_1⟩ |}] let%expect_test _ = check_frame (Sh.star (Sh.seg {loc= l; bas= b; len= m; siz= n; cnt= a}) (Sh.seg {loc= l2; bas= b; len= m; siz= n; cnt= a2})) [] (Sh.seg {loc= l; bas= b; len= m; siz= n; cnt= a}) ; [%expect {| ( infer_frame: 6 %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ * %l_7 -[ %b_4, %m_8 )-> ⟨%n_9,%a_2⟩ \- %l_6 -[ %b_4, %m_8 )-> ⟨%n_9,%a_1⟩ ) infer_frame: %l_7 -[ %b_4, %m_8 )-> ⟨%n_9,%a_2⟩ |}] let%expect_test _ = check_frame (Sh.star (Sh.seg {loc= l; bas= l; len= !16; siz= !8; cnt= a}) (Sh.seg {loc= l + !8; bas= l; len= !16; siz= !8; cnt= a2})) [a3_] (Sh.seg {loc= l; bas= l; len= !16; siz= !16; cnt= a3}) ; [%expect {| ( infer_frame: 7 %l_6 -[)-> ⟨8,%a_1⟩^⟨8,%a_2⟩ \- ∃ %a_3 . %l_6 -[)-> ⟨16,%a_3⟩ ) infer_frame: (⟨8,%a_1⟩^⟨8,%a_2⟩) = %a_3 ∧ emp |}] let%expect_test _ = check_frame (Sh.star (Sh.seg {loc= l; bas= l; len= !16; siz= !8; cnt= a}) (Sh.seg {loc= l + !8; bas= l; len= !16; siz= !8; cnt= a2})) [a3_; m_] (Sh.seg {loc= l; bas= l; len= m; siz= !16; cnt= a3}) ; [%expect {| ( infer_frame: 8 %l_6 -[)-> ⟨8,%a_1⟩^⟨8,%a_2⟩ \- ∃ %a_3, %m_8 . %l_6 -[ %l_6, %m_8 )-> ⟨16,%a_3⟩ ) infer_frame: 16 = %m_8 ∧ (⟨8,%a_1⟩^⟨8,%a_2⟩) = %a_3 ∧ emp |}] let%expect_test _ = check_frame (Sh.star (Sh.seg {loc= l; bas= l; len= !16; siz= !8; cnt= a}) (Sh.seg {loc= l + !8; bas= l; len= !16; siz= !8; cnt= a2})) [a3_; m_] (Sh.seg {loc= l; bas= l; len= m; siz= m; cnt= a3}) ; [%expect {| ( infer_frame: 9 %l_6 -[)-> ⟨8,%a_1⟩^⟨8,%a_2⟩ \- ∃ %a_3, %m_8 . %l_6 -[ %l_6, %m_8 )-> ⟨%m_8,%a_3⟩ ) infer_frame: 16 = %m_8 ∧ (⟨8,%a_1⟩^⟨8,%a_2⟩) = %a_3 ∧ emp |}] let%expect_test _ = check_frame (Sh.star (Sh.seg {loc= k; bas= k; len= !16; siz= !32; cnt= a}) (Sh.seg {loc= l; bas= l; len= !8; siz= !8; cnt= !16})) [a2_; m_; n_] (Sh.star (Sh.seg {loc= l; bas= l; len= !8; siz= !8; cnt= n}) (Sh.seg {loc= k; bas= k; len= m; siz= n; cnt= a2})) ; [%expect {| ( infer_frame: 10 %k_5 -[ %k_5, 16 )-> ⟨32,%a_1⟩ * %l_6 -[)-> ⟨8,16⟩ \- ∃ %a_2, %m_8, %n_9 . %k_5 -[ %k_5, %m_8 )-> ⟨%n_9,%a_2⟩ * %l_6 -[)-> ⟨8,%n_9⟩ ) infer_frame: ∃ %a0_10, %a1_11 . %a_2 = %a0_10 ∧ 16 = %m_8 = %n_9 ∧ (⟨16,%a_2⟩^⟨16,%a1_11⟩) = %a_1 ∧ (16 + %k_5) -[ %k_5, 16 )-> ⟨16,%a1_11⟩ |}] let%expect_test _ = infer_frame (Sh.star (Sh.seg {loc= k; bas= k; len= !16; siz= !32; cnt= a}) (Sh.seg {loc= l; bas= l; len= !8; siz= !8; cnt= !16})) [a2_; m_; n_] (Sh.star (Sh.seg {loc= k; bas= k; len= m; siz= n; cnt= a2}) (Sh.seg {loc= l; bas= l; len= !8; siz= !8; cnt= n})) ; [%expect {| ( infer_frame: 11 %k_5 -[ %k_5, 16 )-> ⟨32,%a_1⟩ * %l_6 -[)-> ⟨8,16⟩ \- ∃ %a_2, %m_8, %n_9 . %k_5 -[ %k_5, %m_8 )-> ⟨%n_9,%a_2⟩ * %l_6 -[)-> ⟨8,%n_9⟩ ) infer_frame: ∃ %a0_10, %a1_11 . %a_2 = %a0_10 ∧ 16 = %m_8 = %n_9 ∧ (⟨16,%a_2⟩^⟨16,%a1_11⟩) = %a_1 ∧ (16 + %k_5) -[ %k_5, 16 )-> ⟨16,%a1_11⟩ |}] let seg_split_symbolically = Sh.star (Sh.seg {loc= l; bas= l; len= !16; siz= 8 * n; cnt= a2}) (Sh.seg {loc= l + (8 * n); bas= l; len= !16; siz= !16 - (8 * n); cnt= a3}) let%expect_test _ = check_frame (Sh.and_ Formula.(or_ (or_ (eq n !0) (eq n !1)) (eq n !2)) seg_split_symbolically) [m_; a_] (Sh.seg {loc= l; bas= l; len= m; siz= m; cnt= a}) ; [%expect {| ( infer_frame: 12 %l_6 -[ %l_6, 16 )-> ⟨8×%n_9,%a_2⟩^⟨(16 + -8×%n_9),%a_3⟩ * ( ( 1 = %n_9 ∧ emp) ∨ ( 0 = %n_9 ∧ emp) ∨ ( 2 = %n_9 ∧ emp) ) \- ∃ %a_1, %m_8 . %l_6 -[ %l_6, %m_8 )-> ⟨%m_8,%a_1⟩ ) infer_frame: ( ( 1 = %n_9 ∧ 16 = %m_8 ∧ (⟨8,%a_2⟩^⟨8,%a_3⟩) = %a_1 ∧ emp) ∨ ( %a_1 = %a_2 ∧ 2 = %n_9 ∧ 16 = %m_8 ∧ (16 + %l_6) -[ %l_6, 16 )-> ⟨0,%a_3⟩) ∨ ( 0 = %n_9 ∧ 16 = %m_8 ∧ (⟨0,%a_2⟩^⟨16,%a_3⟩) = %a_1 ∧ emp) ) |}] (* Incompleteness: equivalent to above but using ≤ instead of ∨ *) let%expect_test _ = infer_frame (Sh.and_ (Formula.le n !2) seg_split_symbolically) [m_; a_] (Sh.seg {loc= l; bas= l; len= m; siz= m; cnt= a}) ; [%expect {| ( infer_frame: 13 (2 ≥ %n_9) ∧ %l_6 -[ %l_6, 16 )-> ⟨8×%n_9,%a_2⟩^⟨(16 + -8×%n_9),%a_3⟩ \- ∃ %a_1, %m_8 . %l_6 -[ %l_6, %m_8 )-> ⟨%m_8,%a_1⟩ ) infer_frame: |}] (* Incompleteness: cannot witness existentials to satisfy non-equality pure constraints *) let%expect_test _ = let subtrahend = Sh.and_ (Formula.eq m a) (Sh.pure (Formula.dq m !0)) in let minuend = Sh.extend_us (Var.Set.of_ a_) Sh.emp in infer_frame minuend [m_] subtrahend ; [%expect {| ( infer_frame: 14 emp \- ∃ %m_8 . %a_1 = %m_8 ∧ (0 ≠ %a_1) ∧ emp ) infer_frame: |}] end )