oadt.lang_oadt.dec

Some decision procedures and implementations.
From oadt Require Import lang_oadt.base.
From oadt Require Import lang_oadt.syntax.
From oadt Require Import lang_oadt.semantics.
From oadt Require Import lang_oadt.infrastructure.
From oadt Require Import lang_oadt.admissible.

Import syntax.notations.
Import semantics.notations.

Decision procedures

Section dec.

The use of abstract is quite important for performance when we run it within Coq.
Ltac t :=
  solve [ repeat
            (try solve [ left; abstract (econstructor; assumption)
                       | right; abstract (inversion 1; subst; contradiction) ];
             try match reverse goal with
                 | H : sumbool _ _ |- _ => destruct H
                 end) ].

#[global]
Instance otval_dec ω : Decision (otval ω).
Proof.
  hnf. induction ω; try t; try case_label; try t.
Defined.


#[global]
Instance oval_dec v : Decision (oval v).
Proof.
  hnf. induction v; try t.

  match goal with
  | H : context [ oval ?ω ] |- context [<{ [inj@_<()> _] }>] =>
    clear H; destruct (decide (otval ω)); try t
  end.
Defined.


#[global]
Instance wval_dec v : Decision (wval v).
Proof.
  hnf. induction v; try t; try case_label; try t.
  - match goal with
    | H : context [ wval ?v] |- context [<{ ~if ?v then _ else _ }>] =>
      clear H; destruct v; try t
    end.
  - match goal with
    | H : context [ wval ?ω], H' : context [ wval ?v ] |-
      context [<{ [inj@_<()> ?v] }>] =>
      clear H; clear H';
        destruct (decide (otval ω)); try t;
        destruct (decide (oval v)); try t
    end.
Defined.


#[global]
Instance woval_dec v : Decision (woval v).
Proof.
  hnf. induction v; try t; try case_label; try t.
  - match goal with
    | H : context [ woval ?v] |- context [<{ ~if ?v then _ else _ }>] =>
      clear H; destruct v; try t
    end.
  - match goal with
    | H : context [ woval ?ω], H' : context [ woval ?v ] |-
      context [<{ [inj@_<()> ?v] }>] =>
      clear H; clear H';
        destruct (decide (otval ω)); try t;
        destruct (decide (oval v)); try t
    end.
Defined.


#[global]
Instance val_dec v : Decision (val v).
Proof.
  hnf. induction v; try t; try case_label; try t.
  match goal with
  | H : context [ val ?ω], H' : context [ val ?v ] |-
      context [<{ [inj@_<()> ?v] }>] =>
      clear H; clear H';
      destruct (decide (otval ω)); try t;
      destruct (decide (oval v)); try t
  end.
Defined.


End dec.

A naive implementation of step


Section step.

Definitions


Context (Σ : gctx).

Fixpoint ovalty_ (ω : expr) : option expr :=
  match ω with
  | <{ 𝟙 }> => mret <{ () }>
  | <{ ~𝔹 }> => mret <{ [true] }>
  | <{ ω1 * ω2 }> => <- ovalty_ ω1; <- ovalty_ ω2; mret <{ (, ) }>
  | <{ ω1 ~+ ω2 }> =>
      guard (otval ω2); v <- ovalty_ ω1; mret <{ [inl<ω1 ~+ ω2> v] }>
  | _ => None
  end.

Fixpoint step_ (e : expr) : option expr :=
  match e with
  | <{ }> =>
    if decide (wval )
    then if decide (wval )
         then match with
              | <{ \:{_}_ => e }> => mret <{ e^ }>
              | <{ ~if [b] then else }> =>
                  mret <{ ~if [b] then else }>
              | _ => None
              end
         else match with
              | <{ gvar X }> =>
                  match Σ !! X with
                  | Some (DOADT _ e') => mret <{ e'^ }>
                  | _ => <- step_ ; mret <{ }>
                  end
              | _ => <- step_ ; mret <{ }>
              end
    else <- step_ ; mret <{ }>
  | <{ let in }> =>
    if decide (wval )
    then mret <{ ^ }>
    else <- step_ ; mret <{ let in }>
  | <{ gvar x }> =>
    match Σ !! x with
    | Some (DFun _ e) => mret e
    | _ => None
    end
  | <{ s𝔹 e }> =>
    if decide (wval e)
    then match e with
         | <{ lit b }> => mret <{ [b] }>
         | <{ ~if [b] then else }> =>
           mret <{ ~if [b] then s𝔹 else s𝔹 }>
         | _ => None
         end
    else e' <- step_ e; mret <{ s𝔹 e' }>
  | <{ if then else }> =>
    if decide (wval )
    then match with
         | <{ lit b }> => mret <{ ite b }>
         | <{ ~if [b] then else }> =>
           mret <{ ~if [b] then (if then else )
                           else (if then else ) }>
         | _ => None
         end
    else <- step_ ; mret <{ if then else }>
  | <{ τ1 * τ2 }> =>
    if decide (otval τ1)
    then <- step_ τ2; mret <{ τ1 * }>
    else <- step_ τ1; mret <{ * τ2 }>
  | <{ (, ) }> =>
    if decide (wval )
    then <- step_ ; mret <{ (, ) }>
    else <- step_ ; mret <{ (, ) }>
  | <{ π@b e }> =>
    if decide (wval e)
    then match e with
         | <{ (, ) }> => mret <{ ite b }>
         | <{ ~if [b'] then else }> =>
          mret <{ ~if [b'] then π@b else π@b }>
         | _ => None
         end
    else e' <- step_ e; mret <{ π@b e' }>
  | <{ τ1 ~+ τ2 }> =>
    if decide (otval τ1)
    then <- step_ τ2; mret <{ τ1 ~+ }>
    else <- step_ τ1; mret <{ ~+ τ2 }>
  | <{ inj@b<τ> e }> => e' <- step_ e; mret <{ inj@b<τ> e' }>
  | <{ ~inj@b<τ> e }> =>
    if decide (otval τ)
    then if decide (oval e)
         then mret <{ [inj@b<τ> e] }>
         else e' <- step_ e; mret <{ ~inj@b<τ> e' }>
    else τ' <- step_ τ; mret <{ ~inj@b<τ'> e }>
  | <{ case of | }> =>
    if decide (wval )
    then match with
         | <{ inj@b<_> v }> => mret <{ ite b (^v) (^v) }>
         | <{ ~if [b] then else }> =>
           mret <{ ~if [b] then (case of | ) else (case of | ) }>
         | _ => None
         end
    else <- step_ ; mret <{ case of | }>
  | <{ ~case of | }> =>
    if decide (wval )
    then match with
         | <{ [inj@b<ω1 ~+ ω2> v] }> =>
            <- ovalty_ ω1; <- ovalty_ ω2;
           mret <{ ~if [b] then (ite b (^v) (^))
                           else (ite b (^) (^v)) }>
         | _ => None
         end
    else <- step_ ; mret <{ ~case of | }>
  | <{ fold<X> e }> => e' <- step_ e; mret <{ fold<X> e' }>
  | <{ unfold<X> e }> =>
    if decide (wval e)
    then match e with
         | <{ fold <_> v }> => mret v
         | <{ ~if [b] then else }> =>
           mret <{ ~if [b] then unfold<X> else unfold<X> }>
         | _ => None
         end
    else e' <- step_ e; mret <{ unfold<X> e' }>
  | <{ tape e }> =>
    if decide (woval e)
    then match e with
         | <{ ~if [b] then else }> =>
           mret <{ mux [b] (tape ) (tape ) }>
         | <{ (, ) }> =>
           mret <{ (tape , tape ) }>
         | <{ () }> => mret <{ () }>
         | <{ [b] }> => mret <{ [b] }>
         | <{ [inj@b<ω> v] }> => mret <{ [inj@b<ω> v] }>
         | _ => None
         end
    else e' <- step_ e; mret <{ tape e' }>
  | <{ mux }> =>
    if decide (wval )
    then if decide (wval )
         then if decide (wval )
              then match with
                   | <{ [b] }> => mret <{ ite b }>
                   | _ => None
                   end
              else <- step_ ; mret <{ mux }>
         else <- step_ ; mret <{ mux }>
    else <- step_ ; mret <{ mux }>
  | <{ ~if then else }> =>
    if decide (wval )
    then if decide (wval )
         then <- step_ ; mret <{ ~if then else }>
         else <- step_ ; mret <{ ~if then else }>
    else <- step_ ; mret <{ ~if then else }>
  | _ => None
  end.

Fixpoint mstep_ (n : ) (e : expr) : expr :=
  match n with
  | 0 => e
  | S n =>
      match step_ e with
      | Some e' => mstep_ n e'
      | None => e
      end
  end.

Correctness


#[local]
Set Default Proof Using "Type".

Notation "e '-->!' e'" := (step Σ e e') (at level 40).
Notation "e '-->*' e'" := (rtc (step Σ) e e') (at level 40).

Lemma ovalty_sound ω : e,
  ovalty_ ω = Some e ->
  ovalty e ω.
Proof.
  induction ω; simpl; intros; try case_label; simplify_eq; simplify_option_eq;
    eauto using ovalty.
Qed.


Lemma step_sound e : e',
  step_ e = Some e' ->
  e -->! e'.
Proof.
  induction e; intros ? H; simplify_eq; simpl in H;
    try (goal_contains <{ _ _ }>; shelve);
    repeat case_decide;
    repeat
      match goal with
      | H : match ?e with _ => _ end = _ |- _ =>
          sdestruct e; simplify_eq
      end; try wval_inv; try woval_inv;
    (* Remove induction hypotheses when they are not needed to avoid unnecessary
    subgoals from simplify_option_eq. *)

    repeat
      match goal with
      | IH : _, step_ ?e = _ -> _ -->! _ |- _ =>
          assert_fails is_var e; clear IH
      end;
    simplify_option_eq;
    try solve [ eauto using step | solve_ctx ].

  eauto using step, ovalty_sound.

  Unshelve.

  repeat case_decide.
  1,3: try case_split; try wval_inv;
  repeat
    match goal with
    | IH : _, step_ ?e = _ -> _ -->! _ |- _ =>
        assert_fails is_var e; clear IH
    end;
  simplify_option_eq;
  try solve [ eauto using step | solve_ctx ].

  match goal with
  | H : ?e = Some ?e' |- ?T =>
      match e with
      | context [step_ ?e >>= ?k] =>
          let H' := fresh in
          assert (step_ e >>= k = Some e' -> T) as H'
              by (clear H; intros; simplify_option_eq; solve_ctx)
      end
  end.

  case_split; eauto.
  repeat case_split; eauto.
  simplify_option_eq.
  eauto using step.
Qed.


Lemma mstep_sound n : e e',
  mstep_ n e = e' ->
  e -->* e'.
Proof.
  induction n; simpl; intros; subst; try reflexivity.
  case_split; try reflexivity.
  eapply rtc_l; eauto using step_sound.
Qed.


End step.