Theory Interval_Transfer

theory Interval_Transfer
  imports
    Interval_Special
    "Voblint_Nonrelational.Nonrelational_Transfer"
begin

section ‹What each kind of CFG edge does to an interval store›

text ‹
  An interval store gives every variable a lower and an upper bound. How an edge
  of a compiled graph moves such a store is not an Interval question --- an
  assignment re-evaluates its right-hand side and overwrites the target, a guard
  runs the backward branch, a return writes into the return variable, procedure
  entry resets the callee frame to const‹ivl_top› and binds the formals, and skip,
  body entry and check observation leave the store alone. That is
  locale‹sound_nonrelational_ops›, proved sound and monotone once for every
  domain that gives one abstract value per variable.

  What is Interval's own are the primitive choices. ‹ivl_ops› collects the
  evaluator, the bound-comparison queries, const‹ivl_refine_ops› --- whose
  comparison inverses make ‹x < 8› tighten ‹x›'s upper bound --- the special
  calls, and const‹ivl_top›. The one interpretation below derives the guard
  filters, the branch, the check classifier and the transfer from that bundle,
  and rewrites the locale's special-call dispatch to const‹special_ivl›,
  Interval's own ‹fun›, rather than introducing a second name for it.
›

lemma interval_check_domain:
  "sound_check_query interval_less interval_eq gamma_state aval_ivl"
  by unfold_locales (rule ivl_arith.aval_abs_sound)

definition ivl_ops :: "ivl nonrelational_ops" where
  "ivl_ops = ⦇ n_aval = aval_ivl, n_query = ⦇q_less = interval_less, q_eq = interval_eq⦈,
               n_refine = ivl_refine_ops, n_special = ivl_special_ops ⦈"

lemma ivl_ops_simps [simp]:
  "n_aval ivl_ops = aval_ivl"
  "q_less (n_query ivl_ops) = interval_less"
  "q_eq (n_query ivl_ops) = interval_eq"
  "n_refine ivl_ops = ivl_refine_ops"
  "n_special ivl_ops = ivl_special_ops"
  by (simp_all add: ivl_ops_def)

global_interpretation ivl_tf: mono_nonrelational_ops ivl_ops
  rewrites "(top :: ivl) = ivl_top"
    and "sound_minmax_ops.special_transfer (n_special ivl_ops) (n_aval ivl_ops) = special_ivl"
  defines assign_ivl = ivl_tf.assign
    and skip_ivl = ivl_tf.skip
    and body_ivl = ivl_tf.body
    and event_ivl = ivl_tf.event
    and return_ivl = ivl_tf.ret
    and enter_frame_ivl_for = ivl_tf.enter_frame_for
    and enter_ivl_for = ivl_tf.enter_for
    and enter_ivl_ci_for = ivl_tf.enter_ci_for
    and ivl_tf_abs = ivl_tf.tf_abs
    and afilter_ivl = ivl_tf.backward.afilter
    and feasible_ivl = ivl_tf.backward.feasible
    and bfilter_ivl = ivl_tf.backward.bfilter
    and branch_ivl = ivl_tf.backward.branch
    and bfilter_lifted_ivl = ivl_tf.backward.bfilter_lifted
    and branch_lifted_ivl = ivl_tf.backward.branch_lifted
    and interval_truthy_query = ivl_tf.check.truthy_query
    and interval_check_query = ivl_tf.check.check_query
    and interval_classify_check = ivl_tf.check.classify_check
    and interval_eval_answer = ivl_tf.check.eval_answer
    and interval_checks_proven = ivl_tf.check.abstract_checks_proven
proof -
  show "mono_nonrelational_ops ivl_ops"
  proof (rule mono_nonrelational_opsI, unfold ivl_ops_simps ivl_refine_ops_simps)
    show "mono_minmax_ops ivl_special_ops aval_ivl"
      by (rule ivl_special.mono_minmax_ops_axioms)
    show "mono_refinement intersect_ivl aval_ivl interval_tobool
            inv_less_ivl inv_eq_ivl inv_conservative inv_conservative inv_conservative"
      by (rule ivl_backward_domain)
    show "sound_check_query interval_less interval_eq gamma_state aval_ivl"
      by (rule interval_check_domain)
  qed
qed (simp_all add: special_ivl_eq_transfer fun_eq_iff top_ivl_def)

text ‹
  No fact is renamed. The transfer functions get Interval-prefixed names above
  because they are constants a caller applies, exported to OCaml and named in
  registration data; the theorems about them stay under ‹ivl_tf.›, which is where
  a reader looks to find out that they are the generic ones rather than
  Interval's own. const‹skip_ivl›'s soundness is ‹ivl_tf.skip_sound›, the
  branch's is ‹ivl_tf.backward.branch_sound›, and the framework's transfer contract at
  Interval is ‹ivl_tf.is_sound_nonrelational_transfer›.
›

end