Theory Example_Interval_DG_Ctx_Flagship

theory Example_Interval_DG_Ctx_Flagship
  imports
    Example_Interval_DG_IP_Flagship
begin

unbundle default_st_syntax

section ‹Context-sensitive interval analysis of ‹twice› (executable)›

text ‹
  The production entry-state analysis
  (theory‹Voblint_Analysis_Interval.Interval_Analyses›) run on
  const‹twice_program›.  Each call to ‹twice› receives the abstract entry state
  of formal ‹p› as its context:

  ▪ ‹twice(3)› uses context ‹[3,3]› and computes ‹#ret = [6,6]› and ‹x = [6,6]›;
  ▪ ‹twice(10)› uses context ‹[10,10]› and computes ‹#ret = [20,20]› and ‹y = [20,20]›.

  The two repeated calls stay separate, whereas the monovariant baseline of
  theory‹Voblint_Examples_Interval.Example_Interval_DG_IP_Flagship› forces one shared entry
  state and reports ‹p = [3,10]›, ‹#ret = [6,20]›, and ‹x = y = [6,20]›.  This
  entry-value key is finite for the two constant call sites.  A general interval
  analysis needs a finite canonical context representation because arbitrary interval
  states may grow under recursion and widening.

  Nothing solver-shaped is owned here: the equation system, its routing hook, the
  solver-global key type type‹global_unknown›, and the solved projection all come from the
  production analysis.  The local unknown carries the whole abstract state on the
  lifted carrier typ‹ivl default_st lifted›, so a global is read where a local is
  and there is no separate solver-global slot holding program state.
›

subsection ‹The executable bottom predicate›

text ‹The equation system reads the program's own declared globals for its bottom
  test. At a concrete program it is const‹default_st_is_bot_for› on those
  globals, which is exact for const‹is_empty_state›.›

definition twice_empty_pred :: "ivl default_st ⇒ bool" where
  "twice_empty_pred = default_st_is_bot_for (declared_global_vars twice_program)"

lemma twice_exact: "twice_empty_pred s = is_empty_state (ρ⇘twice_gs⇙ s)"
  unfolding twice_empty_pred_def by (rule default_st_is_bot_for_iff) simp

text ‹Reading one variable off a lifted whole-state local unknown: an unreachable
  point (const‹Bot›) reads ‹bot› at every variable.›
abbreviation twice_ctx_lookup :: "ivl default_st lifted ⇒ vname ⇒ ivl" where
  "twice_ctx_lookup d x ≡
     (case d of Bot ⇒ bot | Lifted d0 ⇒ d0⟨location_of twice_gs x⟩)"

subsection ‹The routed equation system and its solution›

text ‹Every value below is Interval's entry-state registration ‹interval_es_rule› at
  const‹Globals_Warrow›. The main context is ‹[]› (‹main› is the root
  activation, no formal binds it).›

definition twice_ctx_sol ::
  "(pp × ivl list) set
     × (pp × ivl list + (unit, ivl list) global_unknown ⇒ (ivl default_st lifted, ivl default_st lifted) dg_state)" where
  "twice_ctx_sol = interval_es_rule.solution Globals_Warrow twice_gs twice_program"

lemma twice_ctx_terminates_c:
  "TD_side_rule_Interp_solve_c Globals_Warrow
     (interval_es_rule.equations twice_gs twice_program)
     (interval_es_rule.root_query twice_program) ≠ None"
  unfolding interval_es_rule.root_query_def by eval

lemma twice_ctx_terminates:
  "interval_es_rule.terminates Globals_Warrow twice_gs twice_program"
  by (rule interval_es_rule.terminates_of_solve_c[OF twice_ctx_terminates_c])

subsection ‹The two calling contexts are distinct›

text ‹The routed callee context is const‹dg_pipeline.ctx_succ›, whose type
  omits the domain, so evaluation inlines its body rather than looking for a code
  equation of its own.›


definition ctx_call1 :: "ivl list" where
  "ctx_call1 = interval_es_rule.ctx_succ Globals_Warrow twice_gs twice_program
                 (Statement 2) [] (CallEdge (Some (STR ''x'')) [(STR ''p'')] [VIMP_Syntax.N 3])
                 (STR ''twice'')"

definition ctx_call2 :: "ivl list" where
  "ctx_call2 = interval_es_rule.ctx_succ Globals_Warrow twice_gs twice_program
                 (Statement 3) [] (CallEdge (Some (STR ''y'')) [(STR ''p'')] [VIMP_Syntax.N 10])
                 (STR ''twice'')"

lemma ctx_call1_val: "ctx_call1 = [Ivl (Fin 3) (Fin 3)]"
  unfolding ctx_call1_def twice_ctx_sol_def twice_empty_pred_def by eval

lemma ctx_call2_val: "ctx_call2 = [Ivl (Fin 10) (Fin 10)]"
  unfolding ctx_call2_def twice_ctx_sol_def twice_empty_pred_def by eval

lemma contexts_distinct: "ctx_call1 ≠ ctx_call2"
  by (simp add: ctx_call1_val ctx_call2_val)

subsection ‹Per-context exact results›

text ‹Callee entry parameter, per context --- against the monovariant ‹p = [3,10]›.›
lemma call1_p_at_entry:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (FunctionEntry (STR ''twice''), ctx_call1)))) (STR ''p'')
     = Ivl (Fin 3) (Fin 3)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call1_def by eval

lemma call2_p_at_entry:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (FunctionEntry (STR ''twice''), ctx_call2)))) (STR ''p'')
     = Ivl (Fin 10) (Fin 10)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call2_def by eval

text ‹Callee result return channel, per context --- ∗‹not› merged into the monovariant
  ‹#ret = [6,20]›.›
lemma call1_ret_at_exit:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (FunctionResult (STR ''twice''), ctx_call1)))) (STR ''#ret'')
     = Ivl (Fin 6) (Fin 6)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call1_def by eval

lemma call2_ret_at_exit:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (FunctionResult (STR ''twice''), ctx_call2)))) (STR ''#ret'')
     = Ivl (Fin 20) (Fin 20)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call2_def by eval

text ‹Caller destinations after each return, where the monovariant baseline reports
  ‹x = y = [6,20]›.›
lemma x_computed:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (Statement 3, [])))) (STR ''x'') = Ivl (Fin 6) (Fin 6)"
  unfolding twice_ctx_sol_def twice_empty_pred_def by eval

lemma y_computed:
  "twice_ctx_lookup (dg_local (snd twice_ctx_sol (Inl (Statement 4, [])))) (STR ''y'') = Ivl (Fin 20) (Fin 20)"
  unfolding twice_ctx_sol_def twice_empty_pred_def by eval

subsection ‹Seed slots and coverage›

text ‹Each call publishes the entered store into its own context's seed slot.  The
  heterogeneous seed channel (const‹routed_call_program› / const‹routed_entry_seed_programs›)
  carries that store in the seed unknown's const‹dg_local› half, the same carrier the
  callee entry reads it back on.›
lemma seed_call1:
  "twice_ctx_lookup
     (dg_local (snd twice_ctx_sol
       (Inr (Activation_Seed (FunctionEntry (STR ''twice'')) ctx_call1))))
     (STR ''p'')
     = Ivl (Fin 3) (Fin 3)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call1_def by eval

lemma seed_call2:
  "twice_ctx_lookup
     (dg_local (snd twice_ctx_sol
       (Inr (Activation_Seed (FunctionEntry (STR ''twice'')) ctx_call2))))
     (STR ''p'')
     = Ivl (Fin 10) (Fin 10)"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call2_def by eval

text ‹The callee entry is materialized once per routed context and never under the
  main context: the two calls are analyzed separately.›
lemma callee_covered_call1: "(FunctionEntry (STR ''twice''), ctx_call1) ∈ fst twice_ctx_sol"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call1_def by eval

lemma callee_covered_call2: "(FunctionEntry (STR ''twice''), ctx_call2) ∈ fst twice_ctx_sol"
  unfolding twice_ctx_sol_def twice_empty_pred_def ctx_call2_def by eval

lemma callee_not_under_main: "(FunctionEntry (STR ''twice''), []) ∉ fst twice_ctx_sol"
  unfolding twice_ctx_sol_def twice_empty_pred_def by eval

unbundle no default_st_syntax

end