Theory Example_Sign_Mixed_Flow

theory Example_Sign_Mixed_Flow
  imports
    "Voblint_VIMP.VIMP_Notation" "Voblint_CLI.Analysis_Certified"
begin

section ‹A mixed flow-sensitive analysis, sound end to end for one program›

text ‹
  One procedure writes a program global and another reads it, so its value crosses
  the calls only through the global. With program globals on the shared channel the
  analyzer keeps ‹Gx› in one flow-insensitive value every point reads: the seed
  ‹0› and the write ‹1› join to non-negative, while ‹x› stays a flow-sensitive
  local. The run is the public const‹run_voblint›, so its soundness is the
  published theorem and nothing here is proved about the placement itself.
›

definition mf_program :: imp_prog where
  "mf_program = program {
     global Gx;
     fun set() { Gx = 1; }
     fun get() { return Gx; }
     fun main() {
       x = 1;
       set();
       y = get();
       __voblint_check(0 < x);
       __voblint_check(0 <= y);
     }
   }"

abbreviation mf_config :: analysis_config where
  "mf_config ≡ Analysis_Config [Sign_Analysis] Globals_Join Ctx_None Program_Globals_Flow_Insensitive"

lemma mf_report:
  "(case run_voblint mf_config mf_program of
      Analysed res ⇒
        map check_verdict (report_checks res) = [Decided Check_Proved, Decided Check_Proved]
    | _ ⇒ False)"
  by eval

text ‹
  Every check a source run reaches holds there. The verdicts are computed; that a
  const‹Check_Proved› verdict holds of the run's store is
  ‹run_voblint_check_sound›.
›

theorem mf_checks_hold:
  fixes s0 s :: store
  assumes s0: "s0 ∈ cinit_stores (declared_global mf_program)"
    and run: "declared_global mf_program, prog_table mf_program
                ⊢ (main_body (prog_table mf_program), s0, []) →p* (residual, s, frs)"
    and chk: "next_check residual = Some (l, e)"
  shows "truthy (⟦e⟧e s)"
proof -
  obtain res where ans: "run_voblint mf_config mf_program = Analysed res"
    and verdicts: "map check_verdict (report_checks res)
                     = [Decided Check_Proved, Decided Check_Proved]"
    using mf_report by (cases "run_voblint mf_config mf_program") auto
  from run_voblint_check_sound [OF s0 run chk ans]
  obtain c where listed: "c ∈ set (report_checks res)"
    and proved: "check_verdict c = Decided Check_Proved ⟶ truthy (⟦e⟧e s)"
    by blast
  have "check_verdict c ∈ set (map check_verdict (report_checks res))"
    using listed by simp
  then have "check_verdict c = Decided Check_Proved"
    unfolding verdicts by simp
  with proved show ?thesis by simp
qed

end