|
|
From stdpp Require Import gmap base relations.
|
|
|
From iris Require Import prelude.
|
|
|
From semantics.ts.systemf_mu_state Require Import lang notation.
|
|
|
(* TODO: everywhere replace the metavar σ for heaps with h *)
|
|
|
|
|
|
(** ** Deterministic reduction *)
|
|
|
|
|
|
Record det_step (e1 : expr) (e2 : expr) := {
|
|
|
det_step_safe h : reducible e1 h;
|
|
|
det_step_det e2' h h' :
|
|
|
contextual_step (e1, h) (e2', h') → e2' = e2 ∧ h' = h
|
|
|
}.
|
|
|
|
|
|
Record det_base_step (e1 e2 : expr) := {
|
|
|
det_base_step_safe h : base_reducible e1 h;
|
|
|
det_base_step_det e2' h h' :
|
|
|
base_step (e1, h) (e2', h') → e2' = e2 ∧ h' = h
|
|
|
}.
|
|
|
|
|
|
Lemma det_base_step_det_step e1 e2 : det_base_step e1 e2 → det_step e1 e2.
|
|
|
Proof.
|
|
|
intros [Hp1 Hp2]. split.
|
|
|
- intros h. destruct (Hp1 h) as (e2' & h' & ?).
|
|
|
eexists e2', h'. by apply base_contextual_step.
|
|
|
- intros e2' h h' ?%base_reducible_contextual_step; [ | done]. by eapply Hp2.
|
|
|
Qed.
|
|
|
|
|
|
(** *** Pure execution lemmas *)
|
|
|
Local Ltac inv_step :=
|
|
|
repeat match goal with
|
|
|
| H : to_val _ = Some _ |- _ => apply of_to_val in H
|
|
|
| H : base_step (?e, ?σ) (?e2, ?σ2) |- _ =>
|
|
|
try (is_var e; fail 1); (* inversion yields many goals if [e] is a variable
|
|
|
and should thus better be avoided. *)
|
|
|
inversion H; subst; clear H
|
|
|
end.
|
|
|
Local Ltac solve_exec_safe := intros; subst; eexists _, _; econstructor; eauto.
|
|
|
Local Ltac solve_exec_detdet := simpl; intros; inv_step; try done.
|
|
|
Local Ltac solve_det_exec :=
|
|
|
subst; intros; apply det_base_step_det_step;
|
|
|
constructor; [solve_exec_safe | solve_exec_detdet].
|
|
|
|
|
|
Lemma det_step_beta x e e2 :
|
|
|
is_val e2 →
|
|
|
det_step (App (@Lam x e) e2) (subst' x e2 e).
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_tbeta e :
|
|
|
det_step ((Λ, e) <>) e.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_unpack e1 e2 x :
|
|
|
is_val e1 →
|
|
|
det_step (unpack (pack e1) as x in e2) (subst' x e1 e2).
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_unop op e v v' :
|
|
|
to_val e = Some v →
|
|
|
un_op_eval op v = Some v' →
|
|
|
det_step (UnOp op e) v'.
|
|
|
Proof. solve_det_exec. by simplify_eq. Qed.
|
|
|
|
|
|
Lemma det_step_binop op e1 v1 e2 v2 v' :
|
|
|
to_val e1 = Some v1 →
|
|
|
to_val e2 = Some v2 →
|
|
|
bin_op_eval op v1 v2 = Some v' →
|
|
|
det_step (BinOp op e1 e2) v'.
|
|
|
Proof. solve_det_exec. by simplify_eq. Qed.
|
|
|
|
|
|
Lemma det_step_if_true e1 e2 :
|
|
|
det_step (if: #true then e1 else e2) e1.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
Lemma det_step_if_false e1 e2 :
|
|
|
det_step (if: #false then e1 else e2) e2.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_fst e1 e2 :
|
|
|
is_val e1 →
|
|
|
is_val e2 →
|
|
|
det_step (Fst (e1, e2)) e1.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
Lemma det_step_snd e1 e2 :
|
|
|
is_val e1 →
|
|
|
is_val e2 →
|
|
|
det_step (Snd (e1, e2)) e2.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_casel e e1 e2 :
|
|
|
is_val e →
|
|
|
det_step (Case (InjL e) e1 e2) (e1 e).
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
Lemma det_step_caser e e1 e2 :
|
|
|
is_val e →
|
|
|
det_step (Case (InjR e) e1 e2) (e2 e).
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
Lemma det_step_unroll e :
|
|
|
is_val e →
|
|
|
det_step (unroll (roll e)) e.
|
|
|
Proof. solve_det_exec. Qed.
|
|
|
|
|
|
(** ** n-step reduction *)
|
|
|
(** Reduce in n steps to an irreducible expression.
|
|
|
(this is ⇝^n from the lecture notes)
|
|
|
*)
|
|
|
Definition red_nsteps (n : nat) e h e' h' := nsteps contextual_step n (e, h) (e', h') ∧ irreducible e' h'.
|
|
|
|
|
|
Lemma det_step_red e e' e'' h h'' n :
|
|
|
det_step e e' →
|
|
|
red_nsteps n e h e'' h'' →
|
|
|
1 ≤ n ∧ red_nsteps (n - 1) e' h e'' h''.
|
|
|
Proof.
|
|
|
intros [Hprog Hstep] Hred.
|
|
|
specialize (Hprog h).
|
|
|
destruct Hred as [Hred Hirred].
|
|
|
destruct n as [ | n].
|
|
|
{ inversion Hred; subst.
|
|
|
exfalso; eapply not_reducible; done.
|
|
|
}
|
|
|
inversion Hred as [ | ??[e1 h1]? Hstep0]; subst. simpl.
|
|
|
apply Hstep in Hstep0 as [<- <-].
|
|
|
split; first lia.
|
|
|
replace (n - 0) with n by lia. done.
|
|
|
Qed.
|
|
|
|
|
|
Lemma contextual_step_red_nsteps n e e' e'' h h' h'':
|
|
|
contextual_step (e, h) (e', h') →
|
|
|
red_nsteps n e' h' e'' h'' →
|
|
|
red_nsteps (S n) e h e'' h''.
|
|
|
Proof.
|
|
|
intros Hstep [Hsteps Hirred].
|
|
|
split; last done.
|
|
|
by econstructor.
|
|
|
Qed.
|
|
|
|
|
|
Lemma nsteps_val_inv n v e' h h' :
|
|
|
red_nsteps n (of_val v) h e' h' → n = 0 ∧ e' = of_val v ∧ h' = h.
|
|
|
Proof.
|
|
|
intros [Hred Hirred]; cbn in *.
|
|
|
destruct n as [ | n].
|
|
|
- inversion Hred; subst. done.
|
|
|
- inversion Hred as [ | ??[e1 h1]]; subst. exfalso. eapply val_irreducible; last done.
|
|
|
rewrite to_of_val. eauto.
|
|
|
Qed.
|
|
|
|
|
|
Lemma nsteps_val_inv' n v e e' h h' :
|
|
|
to_val e = Some v →
|
|
|
red_nsteps n e h e' h' → n = 0 ∧ e' = of_val v ∧ h' = h.
|
|
|
Proof. intros Ht. rewrite -(of_to_val _ _ Ht). apply nsteps_val_inv. Qed.
|
|
|
|
|
|
Lemma red_nsteps_fill K k e e' h h' :
|
|
|
red_nsteps k (fill K e) h e' h' →
|
|
|
∃ j e'' h'', j ≤ k ∧
|
|
|
red_nsteps j e h e'' h'' ∧
|
|
|
red_nsteps (k - j) (fill K e'') h'' e' h'.
|
|
|
Proof.
|
|
|
intros [Hsteps Hirred].
|
|
|
induction k as [ | k IH] in e, e', h, h', Hsteps, Hirred |-*.
|
|
|
- inversion Hsteps; subst.
|
|
|
exists 0, e, h'. split_and!; [done | split | ].
|
|
|
+ constructor.
|
|
|
+ by eapply irreducible_fill.
|
|
|
+ done.
|
|
|
- inversion Hsteps as [ | n [e1 h1] [e2 h2] [e3 h3] Hstep Hsteps' Heq1 Heq2 Heq3]. subst.
|
|
|
destruct (contextual_ectx_step_case _ _ _ _ _ Hstep) as [(e'' & -> & Hstep') | Hv].
|
|
|
+ apply IH in Hsteps' as (j & e3 & h3 & ? & Hsteps' & Hsteps''); last done.
|
|
|
eexists (S j), _, _. split_and!; [lia | | done ].
|
|
|
eapply contextual_step_red_nsteps; done.
|
|
|
+ exists 0, e, h. split_and!; [ lia | | ].
|
|
|
* split; [constructor | ].
|
|
|
apply val_irreducible. by apply is_val_spec.
|
|
|
* simpl. by eapply contextual_step_red_nsteps.
|
|
|
Qed.
|
|
|
|
|
|
(** * Heap execution lemmas *)
|
|
|
Lemma new_step_inv v e e' σ σ' :
|
|
|
to_val e = Some v →
|
|
|
base_step (New e, σ) (e', σ') →
|
|
|
∃ l, e' = (Lit $ LitLoc l) ∧ σ' = init_heap l 1 v σ ∧ σ !! l = None.
|
|
|
Proof.
|
|
|
intros <-%of_to_val.
|
|
|
inversion 1; subst.
|
|
|
rewrite to_of_val in H5. injection H5 as [= ->].
|
|
|
eauto.
|
|
|
Qed.
|
|
|
|
|
|
Lemma new_nsteps_inv n v e e' σ σ' :
|
|
|
to_val e = Some v →
|
|
|
red_nsteps n (New e) σ e' σ' →
|
|
|
(n = 1 ∧ base_step (New e, σ) (e', σ')).
|
|
|
Proof.
|
|
|
intros <-%of_to_val [Hsteps Hirred%not_reducible].
|
|
|
inversion Hsteps; subst.
|
|
|
- exfalso; apply Hirred. eapply base_reducible_reducible. eexists _, _. eapply new_fresh.
|
|
|
- destruct y.
|
|
|
eapply base_reducible_contextual_step in H.
|
|
|
2: { eexists _, _. apply new_fresh. }
|
|
|
inversion H0; subst.
|
|
|
{ eauto. }
|
|
|
eapply new_step_inv in H; last apply to_of_val.
|
|
|
destruct H as (l & -> & -> & ?).
|
|
|
destruct y. apply val_stuck in H1. done.
|
|
|
Qed.
|
|
|
|
|
|
Lemma load_step_inv e v σ e' σ' :
|
|
|
to_val e = Some v →
|
|
|
base_step (Load e, σ) (e', σ') →
|
|
|
∃ (l : loc) v', v = #l ∧ σ !! l = Some v' ∧ e' = of_val v' ∧ σ' = σ.
|
|
|
Proof.
|
|
|
intros <-%of_to_val.
|
|
|
inversion 1; subst.
|
|
|
symmetry in H0. apply of_val_lit in H0 as ->.
|
|
|
eauto 8.
|
|
|
Qed.
|
|
|
|
|
|
Definition sub_redexes_are_values (e : expr) :=
|
|
|
∀ K e', e = fill K e' → to_val e' = None → K = empty_ectx.
|
|
|
|
|
|
Lemma contextual_base_reducible e σ :
|
|
|
reducible e σ → sub_redexes_are_values e → base_reducible e σ.
|
|
|
Proof.
|
|
|
intros (e' & σ' & Hstep) ?. inversion Hstep; subst.
|
|
|
assert (K = empty_ectx) as -> by eauto 10 using val_base_stuck.
|
|
|
rewrite fill_empty /base_reducible; eauto.
|
|
|
Qed.
|
|
|
|
|
|
|
|
|
Ltac solve_sub_redexes_are_values :=
|
|
|
let K := fresh "K" in
|
|
|
let e' := fresh "e'" in
|
|
|
let Heq := fresh "Heq" in
|
|
|
let Hv := fresh "Hv" in
|
|
|
let IH := fresh "IH" in
|
|
|
let Ki := fresh "Ki" in
|
|
|
let Ki' := fresh "Ki'" in
|
|
|
intros K e' Heq Hv;
|
|
|
destruct K as [ | Ki K]; first (done);
|
|
|
exfalso; induction K as [ | Ki' K IH] in e', Ki, Hv, Heq |-*;
|
|
|
[destruct Ki; inversion Heq; subst; simplify_val; cbn in *; congruence
|
|
|
| eapply IH; first (by rewrite Heq);
|
|
|
apply fill_item_no_val; done].
|
|
|
|
|
|
Lemma load_nsteps_inv n v e e' σ σ' :
|
|
|
to_val e = Some v →
|
|
|
red_nsteps n (Load e) σ e' σ' →
|
|
|
(n = 0 ∧ σ' = σ ∧ e' = Load e ∧ ¬ reducible (Load e) σ) ∨
|
|
|
(n = 1 ∧ base_step (Load e, σ) (e', σ')).
|
|
|
Proof.
|
|
|
intros <-%of_to_val [Hsteps Hirred%not_reducible].
|
|
|
inversion Hsteps; subst.
|
|
|
- by left.
|
|
|
- right. destruct y.
|
|
|
eapply base_reducible_contextual_step in H.
|
|
|
2: { eapply contextual_base_reducible; [eexists _, _; done | solve_sub_redexes_are_values]. }
|
|
|
inversion H0; subst.
|
|
|
{ eauto. }
|
|
|
eapply load_step_inv in H as (l & ? & -> & ? & -> & ->); last apply to_of_val.
|
|
|
destruct y. apply val_stuck in H1. simplify_val. done.
|
|
|
Qed.
|
|
|
|
|
|
(** useful derived lemma when we know upfront that l satisfies some invariant [P] *)
|
|
|
Lemma load_nsteps_inv' n l e e' σ σ' (P : val → Prop) :
|
|
|
to_val e = Some (LitV $ LitLoc l) →
|
|
|
(∃ v', σ !! l = Some v' ∧ P v') →
|
|
|
red_nsteps n (Load e) σ e' σ' →
|
|
|
∃ v' : val, n = 1 ∧ e' = v' ∧ σ' = σ ∧ σ !! l = Some v' ∧ P v'.
|
|
|
Proof.
|
|
|
intros <-%of_to_val (v' & Hlook & HP) Hred.
|
|
|
eapply load_nsteps_inv in Hred; last done.
|
|
|
destruct Hred as [(-> & -> & -> & Hnred) | (-> & Hstep)].
|
|
|
- exfalso; eapply Hnred. eexists v', _.
|
|
|
eapply base_contextual_step. econstructor. done.
|
|
|
- exists v'. split; first done.
|
|
|
eapply load_step_inv in Hstep; last done.
|
|
|
destruct Hstep as (l' & v'' & [= <-] & ? & -> & ->).
|
|
|
split; first by simplify_option_eq.
|
|
|
split; last done. econstructor; done.
|
|
|
Qed.
|
|
|
|
|
|
Lemma store_step_inv v1 v2 σ e' σ' :
|
|
|
base_step (Store (of_val v1) (of_val v2), σ) (e', σ') →
|
|
|
∃ (l : loc) v', v1 = #l ∧ σ !! l = Some v' ∧ e' = Lit LitUnit ∧ σ' = <[l := v2]> σ.
|
|
|
Proof.
|
|
|
inversion 1; subst.
|
|
|
symmetry in H0. apply of_val_lit in H0 as ->.
|
|
|
simplify_val. simplify_option_eq.
|
|
|
eauto 8.
|
|
|
Qed.
|
|
|
|
|
|
Lemma store_nsteps_inv n v1 v2 e' σ σ' :
|
|
|
red_nsteps n (Store (of_val v1) (of_val v2)) σ e' σ' →
|
|
|
(n = 0 ∧ σ' = σ ∧ e' = Store (of_val v1) (of_val v2) ∧ ¬ reducible (Store (of_val v1) (of_val v2)) σ) ∨
|
|
|
(n = 1 ∧ base_step (Store (of_val v1) (of_val v2), σ) (e', σ')).
|
|
|
Proof.
|
|
|
intros [Hsteps Hirred%not_reducible].
|
|
|
inversion Hsteps; subst.
|
|
|
- by left.
|
|
|
- right. destruct y.
|
|
|
eapply base_reducible_contextual_step in H.
|
|
|
2: { eapply contextual_base_reducible; [eexists _, _; done | solve_sub_redexes_are_values]. }
|
|
|
inversion H0; subst.
|
|
|
{ eauto. }
|
|
|
apply store_step_inv in H as (l & ? & -> & ? & -> & ->).
|
|
|
destruct y. apply val_stuck in H1. simplify_val. done.
|
|
|
Qed.
|
|
|
|
|
|
Lemma store_nsteps_inv' n e1 e2 v0 v l e' σ σ' :
|
|
|
to_val e1 = Some (LitV $ LitLoc l) →
|
|
|
to_val e2 = Some v →
|
|
|
σ !! l = Some v0 →
|
|
|
red_nsteps n (Store e1 e2) σ e' σ' →
|
|
|
n = 1 ∧ e' = Lit $ LitUnit ∧ σ' = <[l := v ]> σ.
|
|
|
Proof.
|
|
|
intros <-%of_to_val <-%of_to_val Hlook Hred%store_nsteps_inv.
|
|
|
destruct Hred as [(-> & -> & -> & Hnred) | (-> & Hb)].
|
|
|
- exfalso; eapply Hnred.
|
|
|
eexists #(), _.
|
|
|
eapply base_contextual_step. econstructor; [done | apply to_of_val ].
|
|
|
- eapply store_step_inv in Hb. destruct Hb as (l' & v' & [= <-] & Hlook' & -> & ->).
|
|
|
simplify_option_eq. done.
|
|
|
Qed.
|
|
|
|
|
|
(** Additionally useful stepping lemmas *)
|
|
|
Lemma app_step_r (e1 e2 e2': expr) h h' :
|
|
|
contextual_step (e2, h) (e2', h') → contextual_step (e1 e2, h) (e1 e2', h').
|
|
|
Proof. by apply (fill_contextual_step [AppRCtx _]). Qed.
|
|
|
|
|
|
Lemma app_step_l (e1 e1' e2: expr) h h' :
|
|
|
contextual_step (e1, h) (e1', h') → is_val e2 → contextual_step (e1 e2, h) (e1' e2, h').
|
|
|
Proof.
|
|
|
intros ? (v & Hv)%is_val_spec.
|
|
|
rewrite <-(of_to_val _ _ Hv).
|
|
|
by apply (fill_contextual_step [AppLCtx _]).
|
|
|
Qed.
|
|
|
|
|
|
Lemma app_step_beta (x: string) (e e': expr) h :
|
|
|
is_val e' → is_closed [x] e → contextual_step ((λ: x, e)%E e', h) (lang.subst x e' e, h).
|
|
|
Proof.
|
|
|
intros Hval Hclosed. eapply base_contextual_step, BetaS; eauto.
|
|
|
Qed.
|
|
|
|
|
|
Lemma unroll_roll_step (e: expr) h :
|
|
|
is_val e → contextual_step ((unroll (roll e))%E, h) (e, h).
|
|
|
Proof.
|
|
|
intros ?; by eapply base_contextual_step, UnrollS.
|
|
|
Qed.
|
|
|
|
|
|
Lemma fill_reducible K e h :
|
|
|
reducible e h → reducible (fill K e) h.
|
|
|
Proof.
|
|
|
intros (e' & h' & Hstep).
|
|
|
exists (fill K e'), h'. eapply fill_contextual_step. done.
|
|
|
Qed.
|
|
|
|
|
|
Lemma reducible_contextual_step_case K e e' h1 h2 :
|
|
|
contextual_step (fill K e, h1) (e', h2) →
|
|
|
reducible e h1 →
|
|
|
∃ e'', e' = fill K e'' ∧ contextual_step (e, h1) (e'', h2).
|
|
|
Proof.
|
|
|
intros [ | Hval]%contextual_ectx_step_case Hred; first done.
|
|
|
exfalso. apply is_val_spec in Hval as (v & Hval).
|
|
|
apply reducible_not_val in Hred. congruence.
|
|
|
Qed.
|
|
|
|
|
|
(** Contextual lifting lemmas for deterministic reduction *)
|
|
|
Tactic Notation "lift_det" uconstr(ctx) :=
|
|
|
intros;
|
|
|
let Hs := fresh in
|
|
|
match goal with
|
|
|
| H : det_step _ _ |- _ => destruct H as [? Hs]
|
|
|
end;
|
|
|
simplify_val; econstructor;
|
|
|
[intros; by eapply (fill_reducible ctx) |
|
|
|
intros ? ? ? (? & -> & [-> ->]%Hs)%(reducible_contextual_step_case ctx); done ].
|
|
|
|
|
|
Lemma det_step_pair_r e1 e2 e2' :
|
|
|
det_step e2 e2' →
|
|
|
det_step (e1, e2)%E (e1, e2')%E.
|
|
|
Proof. lift_det [PairRCtx _]. Qed.
|
|
|
|
|
|
Lemma det_step_pair_l e1 e1' e2 :
|
|
|
is_val e2 →
|
|
|
det_step e1 e1' →
|
|
|
det_step (e1, e2)%E (e1', e2)%E.
|
|
|
Proof. lift_det [PairLCtx _]. Qed.
|
|
|
Lemma det_step_binop_r e1 e2 e2' op :
|
|
|
det_step e2 e2' →
|
|
|
det_step (BinOp op e1 e2)%E (BinOp op e1 e2')%E.
|
|
|
Proof. lift_det [BinOpRCtx _ _]. Qed.
|
|
|
Lemma det_step_binop_l e1 e1' e2 op :
|
|
|
is_val e2 →
|
|
|
det_step e1 e1' →
|
|
|
det_step (BinOp op e1 e2)%E (BinOp op e1' e2)%E.
|
|
|
Proof. lift_det [BinOpLCtx _ _]. Qed.
|
|
|
Lemma det_step_if e e' e1 e2 :
|
|
|
det_step e e' →
|
|
|
det_step (If e e1 e2)%E (If e' e1 e2)%E.
|
|
|
Proof. lift_det [IfCtx _ _]. Qed.
|
|
|
Lemma det_step_app_r e1 e2 e2' :
|
|
|
det_step e2 e2' →
|
|
|
det_step (App e1 e2)%E (App e1 e2')%E.
|
|
|
Proof. lift_det [AppRCtx _]. Qed.
|
|
|
Lemma det_step_app_l e1 e1' e2 :
|
|
|
is_val e2 →
|
|
|
det_step e1 e1' →
|
|
|
det_step (App e1 e2)%E (App e1' e2)%E.
|
|
|
Proof. lift_det [AppLCtx _]. Qed.
|
|
|
Lemma det_step_snd_lift e e' :
|
|
|
det_step e e' →
|
|
|
det_step (Snd e)%E (Snd e')%E.
|
|
|
Proof. lift_det [SndCtx]. Qed.
|
|
|
Lemma det_step_fst_lift e e' :
|
|
|
det_step e e' →
|
|
|
det_step (Fst e)%E (Fst e')%E.
|
|
|
Proof. lift_det [FstCtx]. Qed.
|
|
|
Lemma det_step_store_r e1 e2 e2' :
|
|
|
det_step e2 e2' →
|
|
|
det_step (Store e1 e2)%E (Store e1 e2')%E.
|
|
|
Proof. lift_det [StoreRCtx _]. Qed.
|
|
|
Lemma det_step_store_l e1 e1' e2 :
|
|
|
is_val e2 →
|
|
|
det_step e1 e1' →
|
|
|
det_step (Store e1 e2)%E (Store e1' e2)%E.
|
|
|
Proof. lift_det [StoreLCtx _]. Qed.
|
|
|
|
|
|
|
|
|
#[global]
|
|
|
Hint Resolve app_step_r app_step_l app_step_beta unroll_roll_step : core.
|
|
|
#[global]
|
|
|
Hint Extern 1 (is_val _) => (simpl; fast_done) : core.
|
|
|
#[global]
|
|
|
Hint Immediate is_val_of_val : core.
|
|
|
|
|
|
#[global]
|
|
|
Hint Resolve det_step_beta det_step_tbeta det_step_unpack det_step_unop det_step_binop det_step_if_true det_step_if_false det_step_fst det_step_snd det_step_casel det_step_caser det_step_unroll : core.
|
|
|
|
|
|
#[global]
|
|
|
Hint Resolve det_step_pair_r det_step_pair_l det_step_binop_r det_step_binop_l det_step_if det_step_app_r det_step_app_l det_step_snd_lift det_step_fst_lift det_step_store_l det_step_store_r : core.
|
|
|
|
|
|
#[global]
|
|
|
Hint Constructors nsteps : core.
|
|
|
|
|
|
#[global]
|
|
|
Hint Extern 1 (is_val _) => simpl : core.
|
|
|
|
|
|
Ltac do_det_step :=
|
|
|
match goal with
|
|
|
| |- nsteps det_step _ _ _ => econstructor 2; first do_det_step
|
|
|
| |- det_step _ _ => simpl; solve[eauto 10]
|
|
|
end.
|