Section with_env.
Variable env:Store Prop.
Fixpoint interp_form (f:form): Prop :=
match f with
[n]=> match get n env with PNone => True | PSome P => P end
| A =>> B => (interp_form A) -> (interp_form B)
| # => False
| A //\\ B => (interp_form A) /\ (interp_form B)
| A \\// B => (interp_form A) \/ (interp_form B)
end.
Notation "[[ A ]]" := (interp_form A).
Fixpoint interp_ctx (hyps:ctx) (F:Full hyps) (G:Prop) {struct F} : Prop :=
match F with
F_empty => G
| F_push H hyps0 F0 =>  interp_ctx hyps0 F0  ([[H]] -> G)
end.
Ltac wipe := intros;simpl;constructor.
induction F;intros A H;simpl;auto.
Qed.
induction F;intros A B H;simpl;auto.
apply IHF;auto.
Qed.
induction F;intros A B C H;simpl;auto.
apply IHF;auto.
Qed.
induction F;intros A B C D H;simpl;auto.
apply IHF;auto.
Qed.
induction F;simpl;intros;auto.
apply compose1 with ([[a]]-> G);auto.
Qed.
induction F;simpl.
contradiction.
intros g H;destruct H.
subst;apply compose0;simpl;trivial.
apply compose1 with [[g]];auto.
Qed.
intros hyps F p g e; apply project_In.
apply get_In with p;assumption.
Qed.
Arguments project [hyps] F [p g] _.
Inductive proof:Set :=
Ax : positive -> proof
| I_Arrow : proof -> proof
| E_Arrow : positive -> positive -> proof -> proof
| D_Arrow : positive -> proof -> proof -> proof
| E_False : positive -> proof
| I_And: proof -> proof -> proof
| E_And: positive -> proof -> proof
| D_And: positive -> proof -> proof
| I_Or_l: proof -> proof
| I_Or_r: proof -> proof
| E_Or: positive -> proof -> proof -> proof
| D_Or: positive -> proof -> proof
| Cut: form -> proof -> proof -> proof.
Notation "hyps \ A" := (push A hyps) (at level 72,left associativity).
Fixpoint check_proof (hyps:ctx) (gl:form) (P:proof) {struct P}: bool :=
match P with
Ax i =>
match get i hyps with
PSome F => form_eq F gl
| _ => false
end
| I_Arrow p =>
match gl with
A  =>> B  => check_proof (hyps \ A) B p
| _ => false
end
| E_Arrow i j p =>
match get i hyps,get j hyps with
PSome A,PSome (B =>>C) =>
form_eq A B && check_proof (hyps \ C) (gl) p
| _,_ => false
end
| D_Arrow i p1 p2 =>
match get i hyps with
PSome  ((A =>>B)=>>C) =>
(check_proof ( hyps \ B =>> C \ A) B p1) && (check_proof (hyps \ C) gl p2)
| _ => false
end
| E_False i =>
match get i hyps with
PSome # => true
| _ => false
end
| I_And p1 p2 =>
match gl with
A //\\ B =>
check_proof hyps A p1 && check_proof hyps B p2
| _ => false
end
| E_And i p =>
match get i hyps with
PSome  (A //\\ B) => check_proof (hyps \ A \ B) gl p
| _=> false
end
| D_And i p =>
match get i hyps with
PSome  (A //\\ B =>> C) => check_proof (hyps \ A=>>B=>>C) gl p
| _=> false
end
| I_Or_l p =>
match gl with
(A \\// B) => check_proof hyps A p
| _ => false
end
| I_Or_r p =>
match gl with
(A \\// B) => check_proof hyps B p
| _ => false
end
| E_Or i p1 p2 =>
match get i hyps with
PSome (A \\// B) =>
check_proof (hyps \ A) gl p1 && check_proof (hyps \ B) gl p2
| _=> false
end
| D_Or i p =>
match get i hyps with
PSome  (A \\// B =>> C) =>
(check_proof (hyps \ A=>>C \ B=>>C) gl p)
| _=> false
end
| Cut A p1 p2 =>
check_proof hyps A p1 && check_proof (hyps \ A) gl p2
end.
induction p; intros hyps F gl.
- (* Axiom *)
simpl;case_eq (get p hyps);clean.
intros f nth_f e;rewrite <- (form_eq_refl e).
apply project with p;trivial.
- (* Arrow_Intro *)
destruct gl; clean.
simpl; intros.
change (interp_ctx (hyps\gl1)  (F_push gl1 hyps F) [[gl2]]).
apply IHp; try constructor; trivial.
- (* Arrow_Elim *)
simpl check_proof; case_eq (get p hyps); clean.
intros f ef; case_eq (get p0 hyps); clean.
intros f0 ef0; destruct f0; clean.
case_eq (form_eq f f0_1); clean.
simpl; intros e check_p1.
generalize  (project  F ef) (project  F ef0)
(IHp (hyps \ f0_2) (F_push f0_2 hyps F) gl check_p1);
clear check_p1 IHp p p0 p1 ef ef0.
simpl.
apply compose3.
rewrite (form_eq_refl e).
auto.
- (* Arrow_Destruct *)
simpl; case_eq (get p1 hyps); clean.
intros f ef; destruct f; clean.
destruct f1; clean.
case_eq (check_proof (hyps \ f1_2 =>> f2 \ f1_1) f1_2 p2); clean.
intros check_p1 check_p2.
generalize (project F ef)
(IHp1 (hyps \ f1_2 =>> f2 \ f1_1)
(F_push f1_1 (hyps \ f1_2 =>> f2)
(F_push (f1_2 =>> f2) hyps F)) f1_2 check_p1)
(IHp2 (hyps \ f2) (F_push f2 hyps F) gl check_p2).
simpl; apply compose3; auto.
- (* False_Elim *)
simpl; case_eq (get p hyps); clean.
intros f ef; destruct f; clean.
intros _; generalize (project F ef).
apply compose1; apply False_ind.
- (* And_Intro *)
simpl; destruct gl; clean.
case_eq (check_proof hyps gl1 p1); clean.
intros Hp1 Hp2;generalize (IHp1 hyps F gl1 Hp1) (IHp2 hyps F gl2 Hp2).
apply compose2 ; simpl; auto.
- (* And_Elim *)
simpl; case_eq (get p hyps); clean.
intros f ef; destruct f; clean.
intro check_p;
generalize  (project F ef)
(IHp (hyps \ f1 \ f2) (F_push f2 (hyps \ f1) (F_push f1 hyps F)) gl check_p).
simpl; apply compose2; intros [h1 h2]; auto.
- (* And_Destruct*)
simpl; case_eq (get p hyps); clean.
intros f ef; destruct f; clean.
destruct f1; clean.
intro H;
generalize (project F ef)
(IHp (hyps \ f1_1 =>> f1_2 =>> f2)
(F_push (f1_1 =>> f1_2 =>> f2) hyps F) gl H);
clear H; simpl.
apply compose2; auto.
- (* Or_Intro_left *)
destruct gl; clean.
intro Hp; generalize (IHp hyps F gl1 Hp).
apply compose1; simpl; auto.
- (* Or_Intro_right *)
destruct gl; clean.
intro Hp; generalize (IHp hyps F gl2 Hp).
apply compose1; simpl; auto.
- (* Or_elim *)
simpl; case_eq (get p1 hyps); clean.
intros f ef; destruct f; clean.
case_eq (check_proof (hyps \ f1) gl p2); clean.
intros check_p1 check_p2;
generalize (project F ef)
(IHp1 (hyps \ f1) (F_push f1 hyps F) gl check_p1)
(IHp2 (hyps \ f2) (F_push f2 hyps F) gl check_p2);
simpl; apply compose3; simpl; intro h; destruct h; auto.
- (* Or_Destruct *)
simpl; case_eq (get p hyps); clean.
intros f ef; destruct f; clean.
destruct f1; clean.
intro check_p0;
generalize (project F ef)
(IHp (hyps \ f1_1 =>> f2 \ f1_2 =>> f2)
(F_push (f1_2 =>> f2) (hyps \ f1_1 =>> f2)
(F_push (f1_1 =>> f2) hyps F)) gl check_p0);
simpl.
apply compose2; auto.
- (* Cut *)
simpl; case_eq (check_proof hyps f p1); clean.
intros check_p1 check_p2;
generalize (IHp1 hyps F f check_p1)
(IHp2 (hyps\f) (F_push f hyps F) gl check_p2);
simpl; apply compose2; auto.
Qed.

Theorem Reflect: forall gl prf, if check_proof empty gl prf then [[gl]] else True.