Lvc.Eqn

Require Import CSet Le.

Require Import Plus Util AllInRel Map.
Require Import CSet Val Var Env EnvTy Equiv.Sim IL Fresh Annotation MoreExp Coherence.

Require Import SetOperations Filter.

Set Implicit Arguments.
Unset Printing Records.

Inductive eqn :=
  | EqnEq (e :exp)
  | EqnApx (e :exp)
  | EqnBot.

Definition satisfies (E:onv val) (gamma:eqn) : Prop :=
match gamma with
| EqnEq e option_R eq (exp_eval E e) (exp_eval E )
| EqnApx e fstNoneOrR eq (exp_eval E e) (exp_eval E )
| EqnBotFalse
end.

Inductive eqnLt : eqneqnProp :=
| EqnLtBotEq e
  : eqnLt EqnBot (EqnEq e )
| EqnLtBotApx e
  : eqnLt EqnBot (EqnApx e )
| EqnLtEqApx e1 e1´ e2 e2´
  : eqnLt (EqnEq e1 e2) (EqnApx e1´ e2´)
| EqnLtEqEq1 e1 e1´ e2 e2´
  : expLt e1 e1´
    → eqnLt (EqnEq e1 e2) (EqnEq e1´ e2´)
| EqnLtEqEq2 e1 e2 e2´
  : expLt e2 e2´
    → eqnLt (EqnEq e1 e2) (EqnEq e1 e2´)
| EqnLtApxApx1 e1 e1´ e2 e2´
  : expLt e1 e1´
    → eqnLt (EqnApx e1 e2) (EqnApx e1´ e2´)
| EqnLtApxApx2 e1 e2 e2´
  : expLt e2 e2´
    → eqnLt (EqnApx e1 e2) (EqnApx e1 e2´).

Instance eqnLt_irr : Irreflexive eqnLt.
hnf; intros; unfold complement.
- induction x; inversion 1; subst; eauto;
  try now eapply expLt_irr; eauto.
Qed.

Instance eqnLt_trans : Transitive eqnLt.
hnf; intros.
inv H; inv H0; eauto using eqnLt, expLt_trans.
Qed.

Instance StrictOrder_eqnLt : OrderedType.StrictOrder eqnLt eq.
econstructor; intros; eauto using eqnLt_trans.
- intro. rewrite H0 in H. eapply eqnLt_irr; eauto.
Qed.

Local Notation "´Compare´ x ´next´ y" :=
  (match x with
    | Eqy
    | zz
  end) (at level 100).

Fixpoint eqn_cmp (e :eqn) :=
  match e, with
    | EqnBot, EqnBotEq
    | EqnBot, _Lt
    | EqnEq _ _, EqnBotGt
    | EqnEq _ _, EqnApx _ _Lt
    | EqnEq e1 e2, EqnEq e1´ e2´
      Compare _cmp e1 e1´ next
      Compare _cmp e2 e2´ next Eq
    | EqnApx e1 e2, EqnApx e1´ e2´
      Compare _cmp e1 e1´ next
      Compare _cmp e2 e2´ next Eq
    | EqnApx _ _, _Gt
  end.

Instance OrderedType_eqn : OrderedType eqn :=
 { _eq := eq;
  _lt := eqnLt;
  _cmp := eqn_cmp}.
intros.
destruct x,y; simpl eqn_cmp; try now (econstructor; eauto using eqnLt).
pose proof (_compare_spec e e0); unfold _cmp in *; simpl in ×.
inv H; try now (econstructor; eauto using eqnLt).
pose proof (_compare_spec e´0); unfold _cmp in *; simpl in ×.
inv H1; try now (econstructor; eauto 20 using eqnLt).
pose proof (_compare_spec e e0); unfold _cmp in *; simpl in ×.
inv H; try now (econstructor; eauto using eqnLt).
pose proof (_compare_spec e´0); unfold _cmp in *; simpl in ×.
inv H1; try now (econstructor; eauto 20 using eqnLt).
Defined.

Definition eqns := set eqn.

Definition satisfiesAll (E:onv val) (Gamma:eqns) :=
   gamma, gamma Gammasatisfies E gamma.

Definition freeVars (gamma:eqn) :=
  match gamma with
    | EqnEq e Exp.freeVars e Exp.freeVars
    | EqnApx e Exp.freeVars e Exp.freeVars
    | EqnBot
  end.

Definition eqns_freeVars (Gamma:eqns) := fold union (map freeVars Gamma) .

Definition entails Gamma Γ´ := E, satisfiesAll E GammasatisfiesAll E Γ´.

Definition not_entails Gamma gamma := E, satisfiesAll E Gamma ¬ satisfies E gamma.

Definition onvLe X (E :onv X)
:= x v, E x = Some v x = Some v.


Lemma exp_eval_onvLe e E v
: onvLe E
  → exp_eval E e = Some v
  → exp_eval e = Some v.
Proof.
  intros. general induction e; simpl in × |- *; eauto.
  simpl in H0. rewrite H0. eapply H in H0. eauto.
  - monad_inv H0. rewrite EQ.
    erewrite IHe; eauto.
  - monad_inv H0. rewrite EQ, EQ1.
    erewrite IHe1, IHe2; eauto.
Qed.

Definition list_EqnApx Y :=
  of_list (zip (fun e EqnApx e ) Y ).

Definition subst_eqn (ϱ : env exp) (gamma: eqn) :=
  match gamma with
    | EqnEq e EqnEq (subst_exp ϱ e) (subst_exp ϱ )
    | EqnApx e EqnApx (subst_exp ϱ e) (subst_exp ϱ )
    | EqnBotEqnBot
  end.

Definition subst_eqns (ϱ : env exp) (G:eqns) : eqns :=
  map (subst_eqn ϱ) G.

Definition sid := fun xVar x.

Definition unsatisfiable (Gamma:eqns) :=
   E, ¬ satisfiesAll E Gamma.