Theory Evaluate_Single
section "Simplifiying the definition: no mutual recursion"
theory Evaluate_Single
imports Evaluate_Clock
begin
fun evaluate_list ::
"('ffi state ⇒ exp ⇒ 'ffi state*(v, v) result) ⇒
'ffi state ⇒ exp list ⇒ 'ffi state*(v list, v) result" where
Nil:
"evaluate_list eval s [] = (s, Rval [])" |
Cons:
"evaluate_list eval s (e#es) =
(case fix_clock s (eval s e) of
(s', Rval v) ⇒
(case evaluate_list eval s' es of
(s'', Rval vs) ⇒ (s'', Rval (v#vs))
| res ⇒ res)
| (s', Rerr err) ⇒ (s', Rerr err))"
lemma evaluate_list_cong[fundef_cong]:
assumes "⋀e s. e ∈ set es1 ⟹ clock s ≤ clock s1 ⟹ eval1 s e = eval2 s e" "s1 = s2" "es1 = es2"
shows "evaluate_list eval1 s1 es1 = evaluate_list eval2 s2 es2"
using assms by (induction es1 arbitrary: es2 s1 s2) (fastforce simp: fix_clock_alt_def split: prod.splits result.splits)+
function (sequential)
evaluate :: " v sem_env ⇒'ffi state ⇒ exp ⇒ 'ffi state*(v,v) result" where
Lit:
"evaluate env s (Lit l) = (s, Rval (Litv l))" |
Raise:
"evaluate env s (Raise e) =
(case evaluate env s e of
(s', Rval v) ⇒ (s', Rerr (Rraise (v)))
| res ⇒ res)" |
Handle:
"evaluate env s (Handle e pes) =
(case evaluate env s e of
(s', Rerr (Rraise v)) ⇒
(case match_result env s' v pes v of
(Rval (e', env')) ⇒
evaluate (env ⦇ sem_env.v := nsAppend (alist_to_ns env') (sem_env.v env) ⦈) s' e'
| (Rerr err) ⇒ (s', Rerr err))
| res ⇒ res)" |
Con:
"evaluate env s (Con cn es) =
(if do_con_check (c env) cn (length es) then
(case evaluate_list (evaluate env) s (rev es) of
(s', Rval vs) ⇒
(case build_conv (c env) cn (rev vs) of
Some v ⇒ (s', Rval v)
| None ⇒ (s', Rerr (Rabort Rtype_error)))
| (s', Rerr err) ⇒ (s', Rerr err))
else (s, Rerr (Rabort Rtype_error)))" |
Var:
"evaluate env s (Var n) =
(case nsLookup (sem_env.v env) n of
Some v ⇒ (s, Rval v)
| None ⇒ (s, Rerr (Rabort Rtype_error)))" |
Fun:
"evaluate env s (Fun n e) = (s, Rval (Closure env n e))" |
App:
"evaluate env s (App op0 es) =
(case evaluate_list (evaluate env) s (rev es) of
(s', Rval vs) ⇒
(if op0 = Opapp then
(case do_opapp (rev vs) of
Some (env', e) ⇒
(if (clock s' = 0) then
(s', Rerr (Rabort Rtimeout_error))
else
evaluate env' (dec_clock s') e)
| None ⇒ (s', Rerr (Rabort Rtype_error)))
else
(case do_app (refs s', ffi s') op0 (rev vs) of
Some ((refs',ffi'), res) ⇒ (s' ⦇refs:=refs',ffi:=ffi'⦈, res)
| None ⇒ (s', Rerr (Rabort Rtype_error))))
| (s', Rerr err) ⇒ (s', Rerr err))" |
Log:
"evaluate env s (Log op0 e1 e2) =
(case evaluate env s e1 of
(s', Rval v) ⇒
(case do_log op0 v e2 of
Some (Exp e') ⇒ evaluate env s' e'
| Some (Val bv) ⇒ (s', Rval bv)
| None ⇒ (s', Rerr (Rabort Rtype_error)))
| res ⇒ res)" |
If:
"evaluate env s (If e1 e2 e3) =
(case evaluate env s e1 of
(s', Rval v) ⇒
(case do_if v e2 e3 of
Some e' ⇒ evaluate env s' e'
| None ⇒ (s', Rerr (Rabort Rtype_error)))
| res ⇒ res)" |
Mat:
"evaluate env s (Mat e pes) =
(case evaluate env s e of
(s', Rval v) ⇒
(case match_result env s' v pes Bindv of
Rval (e', env') ⇒
evaluate (env ⦇ sem_env.v := nsAppend (alist_to_ns env') (sem_env.v env) ⦈) s' e'
| Rerr err ⇒ (s', Rerr err))
| res ⇒ res)" |
Let:
"evaluate env s (Let n e1 e2) =
(case evaluate env s e1 of
(s', Rval v) ⇒
evaluate ( env ⦇ sem_env.v := (nsOptBind n v(sem_env.v env)) ⦈) s' e2
| res ⇒ res)" |
Letrec:
"evaluate env s (Letrec funs e) =
(if distinct (List.map (λx. (case x of (x,y,z) => x )) funs) then
evaluate ( env ⦇ sem_env.v := (build_rec_env funs env(sem_env.v env)) ⦈) s e
else
(s, Rerr (Rabort Rtype_error)))" |
Tannot:
"evaluate env s (Tannot e t0) = evaluate env s e" |
Lannot:
"evaluate env s (Lannot e l) = evaluate env s e"
by pat_completeness auto
context
notes do_app.simps[simp del]
begin
lemma match_result_elem:
assumes "match_result env s v0 pes err_v = Rval (e, env')"
shows "∃pat. (pat, e) ∈ set pes"
using assms proof (induction pes)
case Nil
then show ?case by auto
next
case (Cons pe pes)
then obtain p e where "pe = (p, e)" by force
show ?case
using Cons(2)
apply (simp add:match_result_alt_def)
unfolding ‹pe = _›
apply (cases "allDistinct (pat_bindings p [])")
apply (cases "pmatch (c env) (refs s) p v0 []")
using Cons(1) by auto+
qed
private lemma evaluate_list_clock_monotone: "clock (fst (evaluate_list eval s es)) ≤ clock s"
apply (induction es arbitrary: s)
apply (auto split:prod.splits result.splits simp add:fix_clock_alt_def dest!:fstI intro:le_trans)
apply (metis state.record_simps(1))+
done
lemma i_hate_words_helper:
"i ≤ (j - k :: nat) ⟹ i ≤ j"
by simp
thm i_hate_words_helper [THEN le_trans, no_vars]
private lemma evaluate_clock_monotone:
‹clock (fst (evaluate env s e)) ≤ clock s›
if ‹evaluate_dom (env, s, e)›
proof -
have *: ‹i ≤ j - k ⟹ j ≤ r ⟹ i ≤ r› for i j k r :: nat
by arith
from that show ?thesis
by induction (fastforce simp add: evaluate.psimps do_con_check_build_conv evaluate_list_clock_monotone
split: prod.splits result.splits option.splits exp_or_val.splits error_result.splits
dest: fstI intro: *)+
qed
private definition fun_evaluate_single_relation where
"fun_evaluate_single_relation = inv_image (less_than <*lex*> less_than) (λx.
case x of (_, s, e) ⇒ (clock s, size_exp' e))"
private lemma pat_elem_less_size:
"(pat, e) ∈ set pes ⟹ size_exp' e < (size_list (size_prod size size_exp') pes)"
by (induction pes) auto
private lemma elem_less_size: "e ∈ set es ⟹ size_exp' e ≤ size_list size_exp' es"
by (induction es) auto
lemma evaluate_total: "All evaluate_dom"
proof (relation "fun_evaluate_single_relation", unfold fun_evaluate_single_relation_def, goal_cases)
case 7
then show ?case
using evaluate_list_clock_monotone "7"(1)[symmetric]
by (auto dest!: fstI simp add:evaluate_list_clock_monotone Suc_le_lessD)
qed (auto simp add: less_Suc_eq_le Suc_le_lessD do_if_def do_log_alt_def evaluate_list_clock_monotone elem_less_size
split:lop.splits v.splits option.splits tid_or_exn.splits if_splits id0.splits list.splits
dest!:evaluate_clock_monotone match_result_elem fstI dest:sym pat_elem_less_size intro:le_neq_implies_less)
termination evaluate by (rule evaluate_total)
lemma evaluate_clock_monotone': "evaluate eval s e = (s', r) ⟹ clock s' ≤ clock s"
using fst_conv evaluate_clock_monotone evaluate_total
by metis
fun evaluate_list' :: "v sem_env ⇒ 'ffi state ⇒ exp list ⇒ 'ffi state*(v list, v) result" where
"evaluate_list' env s [] = (s, Rval [])" |
"evaluate_list' env s (e#es) =
(case evaluate env s e of
(s', Rval v) ⇒
(case evaluate_list' env s' es of
(s'', Rval vs) ⇒ (s'', Rval (v#vs))
| res ⇒ res)
| (s', Rerr err) ⇒ (s', Rerr err))"
lemma fix_clock_evaluate[simp]: "fix_clock s (evaluate eval s e) = evaluate eval s e"
unfolding fix_clock_alt_def
apply (auto simp: datatype_record_update split: state.splits prod.splits)
using evaluate_clock_monotone' by fastforce
lemma evaluate_list_eq[simp]: "evaluate_list (evaluate env) = evaluate_list' env"
apply (rule ext)+
subgoal for s es
by (induction rule:evaluate_list'.induct) (auto split:prod.splits result.splits)
done
declare evaluate_list.simps[simp del]
lemma fun_evaluate_equiv:
"fun_evaluate_match s env v pes err_v = (case match_result env s v pes err_v of
Rerr err ⇒ (s, Rerr err)
| Rval (e, env') ⇒ evaluate_list (evaluate (env ⦇ sem_env.v := (nsAppend (alist_to_ns env') (sem_env.v env)) ⦈)) s [e])"
"fun_evaluate s env es = evaluate_list (evaluate env) s es"
by (induction rule: fun_evaluate_induct)
(auto split: prod.splits result.splits match_result.splits option.splits exp_or_val.splits
if_splits match_result.splits error_result.splits
simp: all_distinct_alt_def)
corollary fun_evaluate_equiv':
"evaluate env s e = map_prod id (map_result hd id) (fun_evaluate s env [e])"
by (subst fun_evaluate_equiv) (simp split: prod.splits result.splits add: error_result.map_id)
end
end