Theory Eval_Class

section ‹A type class for correspondence between HOL expressions and terms›

theory Eval_Class
imports
  "../Rewriting/Rewriting_Term"
  "../Utils/ML_Utils"
  Deriving.Derive_Manager
  "Dict_Construction.Dict_Construction"
begin

no_notation Mpat_Antiquot.mpaq_App (infixl ‹$$› 900)
hide_const (open) Strong_Term.wellformed
declare Strong_Term.wellformed_term_def[simp del]

class evaluate =
  fixes eval :: "rule fset ⇒ term ⇒ 'a ⇒ bool" (‹_/ ⊢/ (_ ≈/ _)› [50,0,50] 50)
  assumes eval_wellformed: "rs ⊢ t ≈ a ⟹ wellformed t"
begin

definition eval' :: "rule fset ⇒ term ⇒ 'a ⇒ bool" (‹_/ ⊢/ (_ ↓/ _)› [50,0,50] 50) where
"rs ⊢ t ↓ a ⟷ wellformed t ∧ (∃t'. rs ⊢ t ⟶* t' ∧ rs ⊢ t' ≈ a)"

lemma eval'I[intro]:
  assumes "wellformed t" "rs ⊢ t ⟶* t'" "rs ⊢ t' ≈ a"
  shows "rs ⊢ t ↓ a"
using assms unfolding eval'_def by auto

lemma eval'E[elim]:
  assumes "rs ⊢ t ↓ a"
  obtains t' where "wellformed t" "rs ⊢ t ⟶* t'" "rs ⊢ t' ≈ a"
using assms unfolding eval'_def by auto

lemma eval_trivI: "rs ⊢ t ≈ a ⟹ rs ⊢ t ↓ a"
by (auto dest: eval_wellformed)

lemma eval_compose:
  assumes "wellformed t" "rs ⊢ t ⟶* t'" "rs ⊢ t' ↓ a"
  shows "rs ⊢ t ↓ a"
proof -
  from ‹rs ⊢ t' ↓ a› obtain t'' where "rs ⊢ t' ⟶* t''" "rs ⊢ t'' ≈ a"
    by blast
  moreover hence "rs ⊢ t ⟶* t''"
    using assms by auto
  ultimately show "rs ⊢ t ↓ a"
    using assms by auto
qed

end

instantiation "fun" :: (evaluate, evaluate) evaluate begin

  definition eval_fun where
  "eval_fun rs t a ⟷ wellformed t ∧ (∀x tx. rs ⊢ tx ↓ x ⟶ rs ⊢ t $ tx ↓ a x)"

  instance
    by standard (simp add: eval_fun_def)

end

corollary eval_funD:
  assumes "rs ⊢ t ≈ f" "rs ⊢ tx ↓ x"
  shows "rs ⊢ t $ tx ↓ f x"
using assms unfolding eval_fun_def by blast

corollary eval'_funD:
  assumes "rs ⊢ t ↓ f" "rs ⊢ tx ↓ x"
  shows "rs ⊢ t $ tx ↓ f x"
proof -
  from assms obtain t' where "rs ⊢ t ⟶* t'" "rs ⊢ t' ≈ f"
    by auto
  have "wellformed (t $ tx)"
    using assms by auto
  moreover have "rs ⊢ t $ tx ⟶* t' $ tx"
    using ‹rs ⊢ t ⟶* t'› by (rule rewrite.rt_fun[unfolded app_term_def])
  moreover have "rs ⊢ t' $ tx ↓ f x"
    using ‹rs ⊢ t' ≈ f› assms(2) by (rule eval_funD)
  ultimately show "rs ⊢ t $ tx ↓ f x"
    by (rule eval_compose)
qed

lemma eval_ext:
  assumes "wellformed f" "⋀x t. rs ⊢ t ↓ x ⟹ rs ⊢ f $ t ↓ a x"
  shows "rs ⊢ f ≈ a"
using assms unfolding eval_fun_def by blast

lemma eval'_ext:
  assumes "wellformed f" "⋀x t. rs ⊢ t ↓ x ⟹ rs ⊢ f $ t ↓ a x"
  shows "rs ⊢ f ↓ a"
apply (rule eval'I[OF ‹wellformed f›])
apply (rule rtranclp.rtrancl_refl)
apply (rule eval_ext)
using assms by auto

lemma eval'_ext_alt:
  fixes f :: "'a::evaluate ⇒ 'b::evaluate"
  assumes "wellformed' 1 t" "⋀u x. rs ⊢ u ↓ x ⟹ rs ⊢ t [u]β ↓ f x"
  shows "rs ⊢ Λ t ↓ f"
proof (rule eval'_ext)
  show "wellformed (Λ t)"
    using assms by simp
next
  fix x :: 'a and u
  assume "rs ⊢ u ↓ x"
  show "rs ⊢ Λ t $ u ↓ f x"
    proof (rule eval_compose)
      show "wellformed (Λ t $ u)"
        using assms ‹rs ⊢ u ↓ x› by auto
    next
      show "rs ⊢ Λ t $ u ⟶* t [u]β"
        using ‹rs ⊢ u ↓ x› by (auto intro: rewrite.beta)
    next
      show "rs ⊢ t [u]β ↓ f x"
        using assms ‹rs ⊢ u ↓ x› by auto
    qed
qed

lemma eval_impl_wellformed[dest]: "rs ⊢ t ≈ a ⟹ wellformed' n t"
by (auto dest: wellformed_inc eval_wellformed[unfolded wellformed_term_def])

lemma eval'_impl_wellformed[dest]: "rs ⊢ t ↓ a ⟹ wellformed' n t"
unfolding eval'_def by (auto dest: wellformed_inc)

lemma wellformed_unpack:
  "wellformed' n (t $ u) ⟹ wellformed' n t"
  "wellformed' n (t $ u) ⟹ wellformed' n u"
  "wellformed' n (Λ t) ⟹ wellformed' (Suc n) t"
by auto

lemma replace_bound_aux:
  "n < 0 ⟷ False"
  "Suc n < Suc m ⟷ n < m"
  "0 < Suc n ⟷ True"
  "((0::nat) = 0) ⟷ True"
  "(0 = Suc m) ⟷ False"
  "(Suc m = Suc n) ⟷ n = m"
  "(Suc m = 0) ⟷ False"
  "(if True then P else Q) = P"
  "(if False then P else Q) = Q"
  "int (0::nat) = 0"
by auto

named_theorems eval_data_intros
named_theorems eval_data_elims

context begin

(* for code generation, used in Tactics.code_tac *)
private definition rewrite_step_term :: "term × term ⇒ term ⇒ term option" where
"rewrite_step_term = rewrite_step"

private lemmas rewrite_rt_fun = rewrite.rt_fun[unfolded app_term_def]
private lemmas rewrite_rt_arg = rewrite.rt_arg[unfolded app_term_def]

ML_file "tactics.ML"

end

method_setup wellformed = ‹Scan.succeed (SIMPLE_METHOD' o Tactics.wellformed_tac)›

end