import struct_tact import .imp_syntax import .imp_common import .imp_eval import .imp_interp import .imp_interp_proof import .imp_interp_nock namespace imp lemma nock_op1_ok : forall op v v', interp.op1 op v = some v' -> interp_nock.op1 op v = v' := begin intros; cases op ; cases v ; cases a; simp [interp_nock.op1], end lemma nock_op2_ok : forall op v1 v2 v', interp.op2 op v1 v2 = some v' -> interp_nock.op2 op v1 v2 = v' := begin intros ; induction op, case binary_op.div { cases v1, case val.int { cases v2, case val.int { simp [interp.op2] at a, by_cases (a_1 = 0); simp * at *, cases a, cases a, trivial, }, all_goals { cases a } }, all_goals { cases a }, }, case binary_op.mod { cases v1, case val.int { cases v2, case val.int { simp [interp.op2] at a, by_cases (a_1 = 0) ; simp * at *, cases a, cases a, trivial, }, all_goals { cases a } }, all_goals { cases a }, }, all_goals { cases v1 ; cases v2 ; cases a; simp [interp_nock.op2] }, end lemma nock_e_ok : forall s h e v, interp.expr s h e = some v → interp_nock.expr s h e = v := begin induction_on e ; intros, case expr.val { cases a_1, simp [interp_nock.expr], }, case expr.var { simp [interp.expr, interp_nock.expr] at *, unfold interp_nock.lookup', break_match, rw a_2 at a_1, cases a_1, rw a_3 at a_1, cases a_1, reflexivity }, case expr.unary_op { simp [interp.expr, interp_nock.expr] at *, simp_option a_2, apply nock_op1_ok, rw ih_1 ; assumption, }, case expr.binary_op { simp [interp.expr, interp_nock.expr] at *, simp_option a_3, simp_option right, apply nock_op2_ok, rw ih_1, rw ih_2, assumption, assumption, assumption, }, case expr.length { simp [interp.expr, interp_nock.expr] at *, simp_option a_1, rw ih_1 v_1, cases v_1 ; break_match, cases right; cases a_3, reflexivity, cases a_3, break_match, cases a_2; simp at right; try { cases right }, break_match; try { cases a_5 }, simp [interp_nock.read', *], assumption, }, case expr.index { simp [interp.expr, interp_nock.expr], break_match, simp [interp.expr] at a_2, simp_option a_2, simp_option right, break_match, cases a_6, cases v_1; cases v_2; dsimp at right_1; try { cases right_1 }, admit, admit, admit, admit, admit, }, end lemma nock_e_ok' : forall s h e v, interp_nock.expr s h e = v -> interp.expr s h e = some v ∨ (forall v', ¬ eval.expr s h e v') := begin intros, subst a, destruct (interp.expr s h e); intros, { right ; intros, delta not ; intros, have eval_not_ok := (eval_expr_interp_expr _ _ _ _ a_1), rw a at eval_not_ok, contradiction }, { rewrite nock_e_ok, left, assumption, assumption } end lemma nocks_e_ok : forall s h es vs, interp.seq_expr s h es = some vs -> interp_nock.seq_expr s h es = vs := begin induction_on es; intros, { simp [interp.seq_expr] at a, cases a, simp [interp_nock.seq_expr] }, { simp [interp_nock.seq_expr, interp.seq_expr] at a_2, simp_option a_2, simp_option right, simp [interp_nock.seq_expr], cases right_1, congr, apply nock_e_ok, assumption, apply ih_1; try { assumption }, } end lemma nock_updates_ok : forall s xs vs s', updates xs vs s = some s' → -- I messed up arg order here. interp_nock.updates' s xs vs = s' := begin intros s xs; revert s, induction xs ; intros, cases vs; simp [updates, interp_nock.updates'] at * ; cases a ; trivial, cases vs, cases a_2, simp [updates] at a_2, simp [interp_nock.updates'], apply ih_1, assumption end lemma nock_s_ok : forall s h p s' h' p', interp.stmt s h p = some (s', h', p') -> interp_nock.stmt s h p = (s', h', p') := begin induction_on p, -- FILL ME IN end lemma nocks_s_done_ok : forall n s h p ret h' v, interp.program n s h p ret = result.done h' v -> interp_nock.program n s h p ret = result.done h' v := begin induction_on n ; intros, { contradiction }, { simp [interp.program, interp_nock.program] at *, repeat { break_if_hyp } ; repeat { break_match_hyp }, rewrite nock_e_ok ; assumption, repeat { break_irrefutable_hyp }, tactic.subst_vars, rewrite nock_s_ok; [return (), assumption ], simp [interp_nock.program], apply ih_1, assumption } end lemma nocks_s_timeout_ok : forall n s h p ret s' h' p', interp.program n s h p ret = result.timeout s' h' p' ret -> interp_nock.program n s h p ret = result.timeout s' h' p' ret := begin intro, induction n ; intros, assumption, simp [interp.program] at a_1, simp [interp_nock.program], break_if, repeat { break_match_hyp }, repeat { break_irrefutable_hyp }, subst a_6, subst a_5, have nock_ok := (nock_s_ok _ _ _ _ _ _ a_3), rw nock_ok, simp [interp_nock.program], apply ih_1 ; assumption end end imp