Library Icharate.Tacs.tacticsDed


Set Implicit Arguments.
Require Export listAux.
Require Export natDedGram.
Require Export semLex.

Ltac inExt :=
match goal with
| |- in_extension ?e ?ex
 try unfold ex;repeat constructor
end.


Ltac elimSig:=
match goal with
H:(sig _)|- _elim H; clear H; intros;elimSig
|H:(sigS _)|-_elim H; clear H; intros;elimSig
| _idtac
end.
Ltac solve_eqdec:=
unfold eqdec; decide equality.

Inductive path : Set :=
  | rP : path
  | lP : path
  | dP : path.

Ltac here :=
   match goal with
   | |- (struct_replace (A:=?A) (I:=?I) (J:=?J)(W:=?W) ?e ?eI ?eJ
           ?Delta ?Delta' ?Gamma ?Gamma') ⇒ econstructor 1
 | |- (replace (A:=?A) (I:=?I) (J:=?J)(W:=?W)
          ?Delta ?Delta' ?Gamma ?Gamma') ⇒ econstructor 1
end.
Ltac down_l :=
   match goal with
   | [ |- (struct_replace (A:=?A) (I:=?I) (J:=?J)(W:=?W) ?eI ?eJ ?r
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 2
 | [ |- (replace (A:=?A) (I:=?I) (J:=?J)(W:=?W)
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 2
end.

Ltac down_r :=
   match goal with
   | [ |- (struct_replace (A:=?A) (I:=?I) (J:=?J)(W:=?W) ?eI ?eJ ?r
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 3
 | [ |- (replace (A:=?A) (I:=?I) (J:=?J)(W:=?W)
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 3
end.
Ltac down_diam :=
   match goal with
   | [ |- (struct_replace (A:=?A) (I:=?I) (J:=?J)(W:=?W) ?eI ?eJ ?e
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 4
 | [ |- (replace (A:=?A) (I:=?I) (J:=?J)(W:=?W)
           ?Delta ?Delta' ?Gamma ?Gamma') ] ⇒ econstructor 4
end.

Implicit Arguments zroot [I J A W].
Ltac unfocus :=
   match goal with
    | |- (natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                     (zfill ?zgamma ?Gamma) ?F) ⇒
        let Gamma' := eval simpl in (zfill zgamma Gamma)
            in change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     Gamma' F)
    | |- ?anygoalidtac
  end.

Ltac z_root :=
    match goal with
    | |- (natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                     (zfill ?zgamma ?Gamma) ?F) ⇒
        let Gamma' := eval simpl in (zfill zgamma Gamma)
            in change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill zroot Gamma') F)
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R ?Gamma ?F
        change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill zroot Gamma) F)
   end.

Ltac z_left :=
  match goal with
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (Comma ?i ?G1 ?G2)) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zleft i z G2) G1) F)
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                   (Comma ?i ?G1 ?G2) ?F
     change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zleft i zroot G2) G1) F)
   | _fail
              
end.

Ltac z_right :=
  match goal with
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (Comma ?i ?G1 ?G2)) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zright i G1 z) G2) F)
  | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (Comma ?i ?G1 ?G2) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zright i G1 zroot) G2) F)
  | _fail
end.

Ltac z_down:= match goal with
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (TDiamond ?j ?G1)) ?F
        change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                (zfill (zdown j z) G1) F)
  | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (TDiamond ?j ?G1) ?F
       change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                (zfill (zdown j zroot) G1) F)
 | _fail

end.

Ltac zpath0 p:=match eval compute in p with
|nilidtac
|cons ?p1 ?plmatch eval compute in p1 with
         |lPz_left;(zpath0 pl)
         |rPz_right;(zpath0 pl)
         |dPz_down;(zpath0 pl)
      end
end.

Ltac zpath p:=z_root;zpath0 p.

Ltac axiom :=
  match goal with
        | H : matches (form (I:=?I)(J:=?J) (A:=?A) ?F) ?Gamma |-
         natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) _ _ _ ?Gamma _
         let x0:= fresh in let e0 := fresh in
     (elim (matches_inv_form H);intros x0 e0;rewrite e0;apply Wd)
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) _ _ _ _ _try apply Wd
 end.

Ltac axiom_auto:=axiom ||auto.
Ltac Gamma_rw H :=
  match goal with
  | H : matches (form (I:=?I)(J:=?J) (A:=?A) ?F) ?Gamma |- ?any
     =>(elim (matches_inv_form H);intros x0 e0;rewrite e0)
  | H : matches (bComma (I:=?I)(J:=?J) (A:=?A) ?i ?B1 ?B2) ?Gamma |- ?any
     ⇒let x := fresh in
        let p := fresh in
         let x0 := fresh in
        let p0 := fresh in
            let H1 := fresh in
        let H2 := fresh in
             let H3 := fresh in
        let H4 := fresh in
         (elim (matches_inv_Comma H);intros x p; elim p; intros x0 p0; elim
             p0; intros H1 H2; elim H2; intros H3 H4; try (rewrite H1))
 
   end.

Ltac slashI nhyp :=
  unfocus; match goal with
    | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) _ _ _ _ (Slash ?i ?F ?G) ⇒
      apply SlashI with (n:=nhyp)
             end.

Ltac slashI0:=slashI 0.
Ltac backI nhyp :=
  unfocus; match goal with
    | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) _ _ _ _ (Backslash ?i ?F ?G) ⇒
      apply BackI with (n:=nhyp)
             end.

Ltac dotI :=
   unfocus; eapply DotI.

Ltac dotE n' p' :=
  match goal with
   | |- natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) _ _ _ (zfill ?z ?gamma) ?F
        eapply DotE' with (n:=n')(p:=p');[try axiom |simpl]
   | |- ?othereapply DotE with (n:=n')(p:=p')
  end.

Ltac dotE0 :=dotE 0 0.
Ltac eslashE := unfocus; eapply SlashE.

Ltac slashE G1 := unfocus; apply SlashE with (G:=G1).

Ltac ebackE := unfocus; eapply BackE.

Ltac backE G1 := unfocus; apply BackE with (G:=G1).

Ltac boxI := unfocus; apply BoxI.

Ltac boxE := unfocus; apply BoxE.

Ltac diamI := unfocus; apply DiamI.

Ltac nthExt n:=
match goal with | |-(in_extension _ ?ext0)=>
match eval compute in n with
 |0 ⇒try unfold ext0;eapply in_extension_rule
 |_try unfold ext0;eapply in_extension_right;nthExt (pred n)
end
end.

Ltac struct n:=eapply Structrule';[nthExt n|autorewrite with ctl_db;auto|simpl].
Ltac structH H:=eapply Structrule';[eexact H|autorewrite with
ctl_db;eauto|simpl].

Inductive contextW (I J W:Set):Set:=
|oneW:WcontextW I J W
|comW:IcontextW I J WcontextW I J WcontextW I J W
|diamW:JcontextW I J WcontextW I J W.

Fixpoint lengthW(I J W:Set)(cw:contextW I J W){struct cw}:nat :=
match cw with
|oneW w⇒ 1
|comW _ t1 t2lengthW t1 + lengthW t2
|diamW _ t1lengthW t1
end.


Fixpoint getContext1 (I J W A:Set)(cw:contextW I J W)(l:list nat)(i:nat)
(lex:Wlist (Form I J A)){struct cw}:
(option (context I J A W)):=
match cw with
| oneW w1match l with
          |a::nilmatch (nth_error (lex w1) a) with
                    |Some fSome (res (word i w1) f)
                    | NoneNone
                   end
          |othersNone
         end
| comW i0 t1 t2match (getSubLists l (lengthW t1)) with
                 |Some (l1, l2)match (getContext1 t1 l1 i lex) with
                        |Some co1match (getContext1 t2 l2 (i+ (lengthW t1))lex) with
                                    |Some co2Some (Comma i0 co1 co2)
                                    |NoneNone
                                               end
                                   |NoneNone
                       end
                |NoneNone
               end
| diamW j t1match (getContext1 t1 l i lex) with
                  |Some co1Some (TDiamond j co1)
                  |NoneNone
           end
end.

Fixpoint getContext (I J W A:Set)(cw:contextW I J W)(l:list nat)(i:nat)
(lex:Wlist (Form I J A)){struct cw}:
nat*(option (context I J A W)):=
match cw with
| oneW w1match (nth_error l i)with
          |Some amatch (nth_error (lex w1) a) with
                    |Some f(i,Some (res (word a w1) f))
                    | None(i, None)
                   end
          |others(i,None)
         end
| comW i0 t1 t2match (getContext t1 l i lex) with
                        |(j, Some co1)match (getContext t2 l (S
                        j) lex) with
                                    |(k,Some co2)(k, Some (Comma i0 co1 co2))
                                    |(i0,None)(i0,None)
                                               end
                                   
                |(k,None)(k,None)
               end
| diamW j t1match (getContext t1 l i lex) with
                  |(m,Some co1)(m, Some (TDiamond j co1))
                  |(m,None)(m, None)
           end
end.

Ltac fits :=
match goal with
| |-(fitsContSent ?lex ?ct ?sent) ⇒
unfold fitsContSent;simpl;try tauto
| _idtac
end.

Ltac setCont cw ln:=
match goal with
| |-(reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?sent ?f)=>
 match eval compute in
(getContext cw ln 0 lex) with
  |(_,(Some ?gamma))apply reduce1 with gamma;
 [simpl|fits]
  |_fail
  end
| |-(deriveTo _ _ _)=> unfold deriveTo;simpl;setCont cw ln
| |-(deriveToSyn _ _ _)=>unfold deriveToSyn;simpl;setCont cw ln
| _idtac
end.

Fixpoint constructList(n:nat):list nat:=
match n with
| 0=> nil
|(S k)=>0::(constructList k)
end.

Ltac setCont0 cw:=setCont cw (constructList (lengthW cw)).

 Ltac pathRep p:=
  match eval compute in p with
  | nilapply replaceRoot
  | (cons ?X1 ?X2) ⇒ match eval compute in X1 with
                           |lPapply replaceLeft; pathRep X2
                           |rPapply replaceRight; pathRep X2
                           |dPapply replaceDiamond; pathRep X2
                             end
   end.

Fixpoint getFirstPathDiam (I J A W:Set)(T:context I J A W)
{struct T}:option (list path):=
match T with
| res _ Fmatch F with
                       |Diamond j BSome (nil(A:=path))
                       | _None
                       end
| Comma i T1 T2match T1 with
                     |res _ (Diamond _ _) ⇒ Some (lP::nil)
                     | _match T2 with
                         | res _ (Diamond _ _) ⇒ Some (rP::nil)
                         | _match (getFirstPathDiam T1) with
                               | Nonematch (getFirstPathDiam T2) with
                                         | NoneNone
                                         | Some p1Some (rP::p1)
                                         end
                               |Some p1Some (lP::p1)
                               end
                           end
                       end
|TDiamond j T1match (getFirstPathDiam T1) with
                     |NoneNone
                     | Some p1Some (dP::p1)
                     end
end.

Ltac elimDiam n':=
match goal with
| |- (natded _ _ _ ?X11 _) ⇒
  match eval compute in (getFirstPathDiam X11) with
 |(None _) ⇒idtac
 | (Some ?p1)=> eapply DiamE with (n:=n'); [pathRep p1 | constructor 1 |idtac]
 end
| |- _idtac
end.


Ltac addAxAux eqdecI eqdecJ ext lex i lw ln :=
match eval compute in (head lw) with
|Some ?m1match eval compute in (head ln) with
 |Some ?n1match eval compute in (nth_error (lex m1) n1) with
 |Some ?f
cut (natded eqdecI eqdecJ ext (res (word i m1) f) f);
[let ax:=fresh "Ax" in (intro ax;simpl in ax)|constructor 1];
addAxAux eqdecI eqdecJ ext lex (S i) (tail lw) (tail ln)
| _idtac
end
|_idtac
end
|_idtac
end.

Ltac addAxioms_anc ln:=match goal with
| |-(deriveToSyn ?gr ?lw ?f)=>
  (addAxAux ((gr.(lexic_syn)).(eqdecI_syn)) ((gr.(lexic_syn)).(eqdecJ_syn))
   (gr.(ext_syn)) ((gr.(lexic_syn)).(lex_syn)) O lw ln)
| _idtac
end.

Ltac addAxioms0_anc :=match goal with
|-(deriveToSyn ?gr ?lw ?f)=>addAxioms_anc (constructList (length lw))
| _idtac
end.

Ltac addAxAuxi eqdecI eqdecJ ext lex lw ln :=
match eval compute in (head lw) with
|Some ?m1match eval compute in (head ln) with
 |Some ?n1match eval compute in (nth_error (lex m1) n1) with
 |Some ?f
cut (natded eqdecI eqdecJ ext (res (word n1 m1) f) f);
[let ax:=fresh "Ax" in (intro ax;simpl in ax)|constructor 1];
addAxAuxi eqdecI eqdecJ ext lex (tail lw) (tail ln)
| _idtac
end
|_idtac
end
|_idtac
end.

Ltac addAxioms ln:=match goal with
| |- (reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f)=>
 addAxAuxi eqdecI eqdecJ ext lex lw ln
| |-(deriveTo _ _ _)=> unfold deriveTo;simpl;addAxioms ln
| |-(deriveToSyn _ _ _)=>unfold deriveToSyn;simpl;addAxioms ln
| _idtac
end.

Ltac addAxioms0 :=match goal with
| |-(reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f)=>
   addAxioms (constructList (length lw))
| |-(deriveTo _ _ _)=> unfold deriveTo;simpl;addAxioms0
| |-(deriveToSyn _ _ _)=>unfold deriveToSyn;simpl;addAxioms0
|_idtac
   
end.


Ltac elimS H1 H2:=
match goal with
| |- (reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f)=>
(let typ:= type of H1 in
(let typ0:= type of H2 in
(match typ with (natded ?eqdecI ?eqdecJ ?ext ?G1 (Slash ?i ?A ?B))=>
match typ0 with (natded ?eqdecI ?eqdecJ ?ext ?G2 ?C)=>
 assert (natded eqdecI eqdecJ ext (Comma i G1 G2) A);
 [(eapply SlashE;[eexact H1|(eexact H2 ||fail)]) |idtac];clear H1; clear H2
 end end)))
|_idtac
end.

Ltac elimB H1 H2:=
match goal with
| |- (reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f)=>
(let typ:= type of H1 in
(let typ0:= type of H2 in
(match typ with (natded ?eqdecI ?eqdecJ ?ext ?G1 (Backslash ?i ?A ?B))=>
match typ0 with (natded ?eqdecI ?eqdecJ ?ext ?G2 ?C)=>
 assert (natded eqdecI eqdecJ ext (Comma i G2 G1) B);
[(eapply BackE;[eexact H2 |(eexact H1 ||fail)])|idtac];clear H1; clear H2
 end end)))
| _idtac
end.

Ltac elimBox H:=let typ:=type of H in
(match typ with (natded ?eqdecI ?eqdecJ ?ext ?G1 (Box ?j ?C))=>
 cut (natded eqdecI eqdecJ ext (TDiamond j G1) C);[intro |apply BoxE;auto];clear H
|_fail
end).


Ltac elimD H1 H2:=
match goal with
| |- (reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f) ⇒
let typ1 := type of H1 in
(let typ2:=type of H2 in
(match typ1 with
|natded ?eqdecI ?eqdecJ ?ext (zfill ?Gamma (TDiamond ?j (res ?r ?F))) ?G
match typ2 with
|natded ?eqdecI ?eqdecJ ?ext ?Delta (Diamond ?i ?F')=>
cut (natded eqdecI eqdecJ ext (zfill Gamma Delta)
G);[clear H1;clear H2;simpl;intro H1|(eapply DiamondE';[eexact H2|(eexact
H1 ||fail)])]
|_fail
end
|_fail
end))
|_fail
end.

Ltac z_rootH H:=let typ := type of H in
(match typ with
    |(natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                     (zfill ?zgamma ?Gamma) ?F) ⇒
        let Gamma' := eval simpl in (zfill zgamma Gamma)
            in (change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill zroot Gamma') F) in H)
   | (natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R ?Gamma ?F) ⇒
        change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill zroot Gamma) F)in H

   end).

Ltac z_leftH H := let typ := type of H in
(match typ with
   | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (Comma ?i ?G1 ?G2)) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zleft i z G2) G1) F) in H
   | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                   (Comma ?i ?G1 ?G2) ?F
     change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zleft i zroot G2) G1) F) in H
   | _fail
              
end).

Ltac z_rightH H :=
 let typ := type of H in
(match typ with
   | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (Comma ?i ?G1 ?G2)) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zright i G1 z) G2) F) in H
   | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (Comma ?i ?G1 ?G2) ?F
      change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                     (zfill (zright i G1 zroot) G2) F) in H
  | _fail
end).

Ltac z_downH H:=
let typ := type of H in
(match typ with
   | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (zfill ?z (TDiamond ?j ?G1)) ?F
        change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                (zfill (zdown j z) G1) F) in H
  | natded (I:=?I)(J:=?J) (A:=?A)(W:=?W) ?dI ?dJ ?R
                (TDiamond ?j ?G1) ?F
       change (natded (I:=I)(J:=J) (A:=A)(W:=W) dI dJ R
                (zfill (zdown j zroot) G1) F)in H
 | _fail

end).

Ltac zpathH0 H p:=match eval compute in p with
|nilidtac
|cons ?p1 ?plmatch eval compute in p1 with
         |lPz_leftH H;(zpathH0 H pl)
         |rPz_rightH H;(zpathH0 H pl)
         |dPz_downH H;(zpathH0 H pl)
      end
end.

Ltac zpathH H p:=z_rootH H;zpathH0 H p.

Ltac endDeriv:=
match goal with
|H : natded _ _ _ _ ?g |- reduceTo ?eqdecI ?eqdecJ ?lex ?ext ?lw ?f
   econstructor;[eauto|fits]
| _idtac
end.

Ltac addHyp n f:=
match goal with
| |-(reduceTo (W:=?W) ?eqdecI ?eqdecJ _ ?ext _ _ )=>
 cut (natded eqdecI eqdecJ ext (res (hyp (W:= W) n) f) f) ;
  [let hyp:= fresh "Hyp" in (intro hyp; simpl in hyp) | axiom]
| |-(natded ?eqdecI ?eqdecJ ?ext _ _)=>
 cut (natded (I:=I)(J:=J)(A:=A) (W:=W) eqdecI eqdecJ ext (res (hyp (W:=W) n) f) f) ;
  [let hyp:=fresh "Hyp" in (intro hyp; simpl in hyp) | axiom]
| _idtac
end.

Definition getHypForm (I J A W:Set)(Gamma:context I J A W):option (Form I J A):=
match Gamma with
|(res (hyp _) f) ⇒ Some f
|otherNone
end.

Ltac introS H :=
let ty:=type of H in
(match ty with
| (natded (I:=?I)(J:=?J)(A:=?A) (W:=?W) ?eqdecI ?eqdecJ ?ext (Comma ?i ?G2 (res (hyp (W:=?W) ?k) ?g)) ?f)=>

  let nv:= fresh in (
 cut (natded eqdecI eqdecJ ext G2 (Slash i f g)) ;
[intro nv;simpl in nv;clear H|eapply SlashI;eexact H])
| (natded ?eqdecI ?eqdecJ ?ext (zfill ?z ?G) ?f)=>simpl in H; introS H
|_fail
end).

Ltac introD j H:=
let ty:=type of H in
(match ty with
| (natded (I:=?I)(J:=?J)(A:=?A) (W:=?W) ?eqdecI ?eqdecJ ?ext ?Gamma
?F)=>
cut (natded eqdecI eqdecJ ext (TDiamond j Gamma) (Diamond j F));[clear
H;intro H|apply DiamI;exact H]
|_fail
end).


Fixpoint getTermByPath(I J A W:Set) (T:context I J A W) (p:list path) {struct p} :
 option (context I J A W):=
  match T, p with
  | T, nilSome T
  | (res _ _ ), cons _ _None
  | Comma i T1 T2, cons p1 p2
      match p1 with
      | lPgetTermByPath T1 p2
      | rPgetTermByPath T2 p2
      | dPNone
      end
  | TDiamond i T, cons p1 p2
      match p1 with
      | dPgetTermByPath T p2
      | otherNone
      end
  end.

Fixpoint replaceTermByTerm (I J A W:Set)(T1 T2:context I J A W) (p:list path) {struct p} :
 option (context I J A W ):=
  match T1, p with
  | _, nilSome T2
  | res _ _, cons _ _None
  | Comma i T'1 T'2, cons p1 p2
      match p1 with
      | lP
          match replaceTermByTerm T'1 T2 p2 with
          | NoneNone
          | Some t'Some (Comma i t' T'2)
          end
      | rP
          match replaceTermByTerm T'2 T2 p2 with
          | NoneNone
          | Some t'Some (Comma i T'1 t')
          end
      | dPNone
      end
  | TDiamond i T, cons p1 p2
      match p1 with
      | dP
          match replaceTermByTerm T T2 p2 with
          | NoneNone
          | Some t'Some (TDiamond i t')
          end
      | otherNone
      end
  end.

Fixpoint getIthRule (I J :Set)(ext:extension I J)(i:nat){struct ext}:
(option (structrule I J)):=
match ext, i with
|NL, _None
|(add_rule r ext1) , 0 ⇒Some r
|(add_rule r ext1) , (S k)=>getIthRule ext1 k
end.


Ltac structL_asc i H:=
let typ:=type of H in (
match typ with
| (natded (I:=?I) (J:=?J) (A:=?A)(W:=?W) ?eqdecI ?eqdecJ ?ext
 (zfill ?z ?Delta1) ?C) ⇒
match eval compute in (getIthRule ext i) with
|Noneidtac
|Some (?ru1,?ru2)
match eval compute in (apply_rule (ru2,ru1) eqdecI eqdecJ Delta1) with
|Some ?Delta2cut (natded eqdecI eqdecJ ext (zfill z
Delta2) C);[simpl;clear H;intro H|(apply XStructrule' with Delta1 (ru1, ru2);[autorewrite with
ctl_db;auto|inExt|exact H])]
|Noneidtac
end
end
|_fail
end).

Ltac structRule i H lemInv:=
let typ:=type of H in (
match typ with
| (natded (I:=?I) (J:=?J) (A:=?A)(W:=?W) ?eqdecI ?eqdecJ ?ext (zfill ?z ?Delta1) ?C) ⇒
match eval simpl in (getIthRule ext i) with
|Noneidtac
|Some ?ru
let hy:=fresh in(
   let delta:=fresh "Delta" in
    (let nd:=fresh in (
      let app:=fresh in (
      let ex:=fresh "E" in (
cut (in_extension ru ext);[intro ex|inExt];
 cut ({Delta2:context I J A W|
      (apply_rule ru eqdecI eqdecJ Delta2)=Some Delta1});
  [intro hy; elim hy; clear hy; intros delta app
 |econstructor;autorewrite with ctl_db;auto];
 cut (natded eqdecI eqdecJ ext (zfill z delta) C);
[intro nd;simpl in nd;
rewrite lemInv with (1:=app) in nd;
 clear ex; clear app ;clear delta;clear H
|eapply XStructrule';eauto])))))
 end
| _idtac
end ).

Ltac structRuleP i H p lem:=zpathH H p;structRule i H lem.


Fixpoint access_tac (I J A W:Set)(eqdecI :eqdec I)(eqdecJ :eqdec
J)(eqdecA:eqdec A)
(rp:rule_pattern I J)(j:nat){struct rp}:(context I J A W)->(option
(context I J A W))*bool:=
match rp with
|pvar imatch (eq_nat_dec i j) with
          |right _fun Gamma:(context I J A W) ⇒(None, true)
          |left _fun Gamma:(context I J A W) ⇒((Some Gamma),true)
          end
|pcomma i rp1 rp2=>(fun Gamma:context I J A W
            match Gamma with
          |Comma l Gamma1 Gamma2match (eqdecI l i) with
                |right _(None,false)
                |left _match (access_tac eqdecI eqdecJ eqdecA rp1 j Gamma1) with
                      |(_, false)(None,false)
                      |(None,true) =>(access_tac eqdecI eqdecJ eqdecA rp2 j Gamma2)
                      |((Some (res (hyp h') ty')),true)
                          match (access_tac eqdecI eqdecJ eqdecA rp2 j Gamma2) with
                       | (_,false)(None,false)
                       |((Some (res (hyp h) ty)), true )
                           match (eq_nat_dec h h') with
                        |left _
                     match (eqDecF eqdecI eqdecJ eqdecA ty ty') with
                     |left _((Some (res (hyp h) ty)),true)
                     |right _(None,false)
                      end
                     |right _(None, false)
                       end
                     |(None,true)((Some (res (hyp h') ty')),true)
                     |other(None, false)
                                    end
                        |((Some Delta),true)
                            match (access_tac eqdecI eqdecJ eqdecA rp2 j Gamma2) with
                              |(None,true)((Some Delta),true)
                              |other(None,false)
                               end end end
                 |other(None,false)
                 end)
|pdiam i rp1 =>(fun Gamma:context I J A W
                 match Gamma with
                   |TDiamond l Gamma1
                 match (eqdecJ i l) with
                   |right _(None,false)
                   |left _ =>(access_tac eqdecI eqdecJ eqdecA rp1 j Gamma1)
                     end
                   |other(None,false)
                     end)
end.

Fixpoint compile_tac (I J A W:Set)(eqdecI :eqdec I)(eqdecJ:eqdec
J)(eqdecA:eqdec A)
(rp1 rp2:rule_pattern I J){struct rp2}:(context I J A W) → (option
(context I J A W)):=
match rp2 with
|pvar ifun Gamma:(context I J A W)=> match (access_tac eqdecI
eqdecJ eqdecA rp1 i Gamma) with
           |((Some Gamma') ,_ )Some Gamma'
           |otherNone
         end
|pcomma i r1 r2fun Gamma:(context I J A W) ⇒
   match (compile_tac eqdecI eqdecJ eqdecA rp1 r1 Gamma) with
          |NoneNone
          |Some Delta1match (compile_tac eqdecI eqdecJ eqdecA rp1 r2 Gamma) with
                    |NoneNone
                    |Some Delta2Some (Comma i Delta1 Delta2)
                      end
                      end
|pdiam i r1fun Gamma:(context I J A W) ⇒
match (compile_tac eqdecI eqdecJ eqdecA rp1 r1 Gamma) with
                    |NoneNone
                    |Some Delta1Some (TDiamond i Delta1)
                      end
end.

 Definition apply_rule_tac(I J A W:Set) (st:structrule I J)(eqdecI: eqdec I)(eqdecJ : eqdec
       J)(eqdecA :eqdec A): context I J A Woption (context I J A W):=
match st with
| (r1,r2)compile_tac eqdecI eqdecJ eqdecA r1 r2
end.

Ltac struct_auxi i H eqdecA:=
let typ:=type of H in (
match typ with
| (natded (I:=?I) (J:=?J) (A:=?A)(W:=?W) ?eqdecI ?eqdecJ ?ext
 (zfill ?z ?Delta1) ?C) ⇒
match eval compute in (getIthRule ext i) with
|Noneidtac
|Some (?ru1,?ru2)
match eval compute in (apply_rule_tac (ru2,ru1) eqdecI eqdecJ eqdecA Delta1) with
|Some ?Delta2cut (natded eqdecI eqdecJ ext (zfill z
Delta2) C);[simpl;clear H;intro H|(eapply XStructrule';[autorewrite with
ctl_db;auto|inExt|eexact H])]
|Noneidtac
end
end
|_fail
end).

Ltac struct_asc i H:=
match goal with
|-deriveToSyn ?gram ?sent ?fstruct_auxi i H ((gram.(lex)).(eqdecA))
|_idtac
end.

Ltac convert_syn:=match goal with
| |-deriveTo _ _ _unfold deriveTo; simpl
end.