Module AbTyps


Require Import ToString Coqlib Utf8 Maps ShareTree Sets Util.
Require Import AdomLib.
Require Import IdealExpr AbIdealEnv.

Module Dom := WPFun T.

Definition t := Dom.t ideal_num_ty.

Instance t_gamma: gamma_op t (var -> ideal_num) := Dom.gamma_tree _.

Instance eq_ty : EqDec ideal_num_ty.
Proof.
intros [] []; auto; right; discriminate. Defined.

Fixpoint traverse_expr (ab:t) (e:iexpr) : t+⊥ :=
  match e with
  | IEvar ty v =>
    match T.get v ab with
    | None => NotBot (T.set v ty ab)
    | Some ty' => if eq_ty ty ty' then NotBot ab else Bot
    end
  | IEconst _ | IEZitv _ => NotBot ab
  | IEunop _ e => traverse_expr ab e
  | IEbinop _ e1 e2 =>
    do ab <- traverse_expr ab e1;
    traverse_expr ab e2
  end.

Lemma traverse_expr_correct:
  ∀ e ab ρ n,
    ρ ∈ γ ab ->
    eval_iexpr ρ e n ->
    ρ ∈ γ (traverse_expr ab e).
Proof.
  induction e.
  - intros. inv H0. simpl. pose proof (H v). unfold Dom.get in H0.
    destruct T.get.
    + destruct i, i0; inv H0; inv H5; try congruence; auto.
    + repeat intro. unfold Dom.get. rewrite T.gsspec.
      destruct T.elt_eq. subst. auto. apply H.
  - intros. auto.
  - intros. auto.
  - intros. inv H0. eapply IHe; eauto.
  - intros. inv H0. eapply botbind_spec; eauto.
Qed.

Program Definition widen (a:t+⊥) (b:(t*query_chan)+⊥) (c:query_chan+⊥)
  : t+⊥ * (t*messages_chan)+⊥ :=
  match a, b return _ with
  | Bot, Bot => (Bot, Bot)
  | Bot, NotBot (r, _) | NotBot r, Bot => (NotBot r, NotBot (r, nil))
  | NotBot (a), NotBot (b, _) =>
    let r := Dom.joinwiden (flat_join_op eq_dec) _ (a:Dom.t ideal_num_ty) b in
    (NotBot r, NotBot (r, nil))
  end.
Next Obligation.
destruct x; reflexivity. Qed.

Definition assign x e (ab:t*query_chan) (c:query_chan) :=
  do ab <- traverse_expr (fst ab) e;
  ret (Dom.set ab x (Just (iexpr_ty e)), nil:messages_chan).

Definition forget x (ab:t*query_chan) (c:query_chan) :=
  NotBot (Dom.set (fst ab) x All, nil:messages_chan).

Definition process_msg m (ab:t*query_chan) :=
  match m with
  | Fact_msg e _ =>
    do ab <- traverse_expr (fst ab) e;
    ret (ab, m::nil)
  | _ => ret (fst ab, m::nil)
  end.

Program Instance abVarExpEq_env : ab_ideal_env t (t+⊥) :=
  {| id_leb a b := Dom.leb_tree (flat_leb_op eq_dec) _ (fst a) b;
     id_top c := NotBot (Dom.top_tree _, nil);
     id_join a b c := NotBot (Dom.joinwiden (flat_join_op eq_dec) _ (fst a) (fst b), nil);
     id_init_iter := id;
     id_widen := widen;
     assign := assign;
     forget := forget;
     enrich_query_chan ab c :=
       {| get_var_ty := fun x => Dom.get x ab;
          get_itv := c.(get_itv);
          get_congr := c.(get_congr);
          get_eq_expr := c.(get_eq_expr);
          linearize_expr := c.(linearize_expr) |};
     process_msg := process_msg
  |}.
Next Obligation.
destruct x; reflexivity. Qed.
Next Obligation.
destruct x; reflexivity. Qed.
Next Obligation.
split. apply Dom.top_tree_correct. constructor. Qed.
Next Obligation.
  eapply Dom.leb_tree_correct, H0. 2:now eauto.
  apply flat_leb_op_correct. intros [] []; try discriminate; reflexivity.
Qed.
Next Obligation.
  split. 2:now constructor. apply Dom.join_tree_correct.
  apply flat_join_op_correct. intros [] []; try discriminate; reflexivity.
  destruct H as [[]|[]]; now auto.
Qed.
Next Obligation.
  destruct ab1, ab2; try contradiction. split. apply H. split. apply H. constructor.
  destruct x0.
  split; [|split;[|constructor]]; apply Dom.join_tree_correct; auto;
  apply flat_join_op_correct; intros [] []; try discriminate; reflexivity.
Qed.
Next Obligation.
  eapply botbind_spec, traverse_expr_correct, H1. 2:now apply H.
  split. 2:now constructor.
  repeat intro. simpl. unfold Dom.get. rewrite T.gsspec.
  destruct T.elt_eq. subst. rewrite upd_s. eapply iexpr_ty_correct, H1.
  rewrite upd_o by auto. apply H2.
Qed.
Next Obligation.
  split. 2:now constructor. repeat intro. simpl. unfold Dom.get. rewrite T.grspec.
  destruct T.elt_eq. constructor. rewrite upd_o by auto. apply H.
Qed.
Next Obligation.
  destruct m; try now (split;[apply H|constructor;[auto|constructor]]).
  eapply botbind_spec, traverse_expr_correct, H0. 2:now apply H.
  split. now auto. constructor. now auto. constructor.
Qed.
Next Obligation.
destruct H0; constructor; simpl; auto. Qed.

Instance t_tostring : ToString t := fun _ => ""%string.