Skip to content

Commit df8ef08

Browse files
authored
Merge pull request #470 from MetaCoq/eval-fix-optimized
Optimizing the fixpoint evaluation rule
2 parents 662169d + 12ae07c commit df8ef08

File tree

6 files changed

+650
-396
lines changed

6 files changed

+650
-396
lines changed

erasure/theories/EArities.v

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -518,14 +518,12 @@ Qed.
518518

519519
Lemma Is_type_eval (Σ : global_env_ext) t v:
520520
wf Σ ->
521+
axiom_free Σ ->
521522
eval Σ t v ->
522523
isErasable Σ [] t ->
523524
isErasable Σ [] v.
524525
Proof.
525526
intros; eapply Is_type_red. eauto.
526-
eapply wcbeval_red; eauto.
527527
red in X1. destruct X1 as [T [HT _]].
528-
eapply typecheck_closed in HT as [_ HT]; auto.
529-
apply andP in HT. now destruct HT.
530-
eauto.
528+
eapply wcbeval_red; eauto. assumption.
531529
Qed.

erasure/theories/EWcbvEval.v

Lines changed: 134 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(* Distributed under the terms of the MIT license. *)
22
Set Warnings "-notation-overridden".
33

4-
From Coq Require Import Arith Bool List Program.
4+
From Coq Require Import Arith Bool List Program Lia.
55
From Equations Require Import Equations.
66
From MetaCoq.Template Require Import config utils.
77
From MetaCoq.Erasure Require Import EAst EAstUtils ELiftSubst ECSubst ETyping.
@@ -52,12 +52,11 @@ Definition cunfold_fix (mfix : mfixpoint term) (idx : nat) :=
5252
| None => None
5353
end.
5454

55-
Definition isStuckFix t args :=
55+
Definition isStuckFix t (args : list term) :=
5656
match t with
5757
| tFix mfix idx =>
5858
match cunfold_fix mfix idx with
59-
| Some (narg, fn) =>
60-
~~ is_nth_constructor_app_or_box narg args
59+
| Some (narg, fn) => #|args| <=? narg
6160
| None => false
6261
end
6362
| _ => false
@@ -114,12 +113,10 @@ Section Wcbv.
114113
eval (tCase (ind, pars) discr brs) res
115114

116115
(** Fix unfolding, with guard *)
117-
| eval_fix f mfix idx argsv a av narg fn res :
116+
| eval_fix f mfix idx argsv a av fn res :
118117
eval f (mkApps (tFix mfix idx) argsv) ->
119118
eval a av ->
120-
cunfold_fix mfix idx = Some (narg, fn) ->
121-
#|argsv| = narg ->
122-
is_constructor_app_or_box av ->
119+
cunfold_fix mfix idx = Some (#|argsv|, fn) ->
123120
eval (tApp (mkApps fn argsv) av) res ->
124121
eval (tApp f a) res
125122

@@ -128,7 +125,7 @@ Section Wcbv.
128125
eval f (mkApps (tFix mfix idx) argsv) ->
129126
eval a av ->
130127
cunfold_fix mfix idx = Some (narg, fn) ->
131-
(#|argsv| <> narg \/ (#|argsv| = narg /\ ~~is_constructor_app_or_box av)) ->
128+
(#|argsv| < narg) ->
132129
eval (tApp f a) (tApp (mkApps (tFix mfix idx) argsv) av)
133130

134131
(** CoFix-case unfolding *)
@@ -285,24 +282,13 @@ Section Wcbv.
285282
apply (value_stuck_fix _ [av]); [easy|].
286283
cbn.
287284
destruct (cunfold_fix mfix idx) as [(? & ?)|]; [|easy].
288-
noconf H1.
289-
destruct H2 as [|(<- & ?)]; [|easy].
290-
unfold is_nth_constructor_app_or_box.
291-
now rewrite (proj2 (nth_error_None _ _));
292-
cbn in *.
285+
noconf H1. destruct narg; auto. lia.
293286
+ easy.
294287
+ eapply value_stuck_fix; [now apply Forall_app_inv|].
295288
unfold isStuckFix in *.
296289
destruct (cunfold_fix mfix idx) as [(? & ?)|]; [|easy].
297-
noconf H1.
298-
unfold is_nth_constructor_app_or_box in *.
299-
destruct H2 as [|(<- & ?)]; [|now rewrite nth_error_snoc].
300-
destruct (Nat.ltb_spec #|argsv| narg).
301-
* rewrite (proj2 (nth_error_None _ _)); [|easy].
302-
rewrite app_length.
303-
cbn.
304-
easy.
305-
* now rewrite nth_error_app1.
290+
noconf H1. rewrite app_length; simpl.
291+
eapply Nat.leb_le. lia.
306292

307293
- destruct (mkApps_elim f' [a']).
308294
eapply value_mkApps_inv in IHeval1 => //.
@@ -320,15 +306,14 @@ Section Wcbv.
320306
rewrite orb_true_r orb_true_l in H0. easy.
321307
Qed.
322308

323-
Lemma closed_unfold_fix_cunfold_eq mfix idx :
309+
Lemma closed_fix_substl_subst_eq {mfix idx d} :
324310
closed (tFix mfix idx) ->
325-
unfold_fix mfix idx = cunfold_fix mfix idx.
311+
nth_error mfix idx = Some d ->
312+
subst0 (fix_subst mfix) (dbody d) = substl (fix_subst mfix) (dbody d).
326313
Proof.
327-
unfold unfold_fix, cunfold_fix.
328-
destruct (nth_error mfix idx) eqn:Heq => //.
329314
move=> /= Hf; f_equal; f_equal.
330315
have clfix : All (closedn 0) (fix_subst mfix).
331-
{ clear Heq d idx.
316+
{ clear idx.
332317
solve_all.
333318
unfold fix_subst.
334319
move: #|mfix| => n.
@@ -340,11 +325,22 @@ Section Wcbv.
340325
now rewrite subst_empty.
341326
move=> Ha; depelim Ha.
342327
simpl in *.
328+
intros hnth.
343329
rewrite -IHfix_subst => //.
344330
rewrite (subst_app_decomp [_]). simpl.
345331
f_equal. rewrite lift_closed // closed_subst //.
346332
Qed.
347333

334+
Lemma closed_unfold_fix_cunfold_eq mfix idx :
335+
closed (tFix mfix idx) ->
336+
unfold_fix mfix idx = cunfold_fix mfix idx.
337+
Proof.
338+
unfold unfold_fix, cunfold_fix.
339+
destruct (nth_error mfix idx) eqn:Heq => //.
340+
intros cl; f_equal; f_equal.
341+
now rewrite (closed_fix_substl_subst_eq cl).
342+
Qed.
343+
348344
Lemma closed_unfold_cofix_cunfold_eq mfix idx :
349345
closed (tCoFix mfix idx) ->
350346
unfold_cofix mfix idx = cunfold_cofix mfix idx.
@@ -390,6 +386,106 @@ Qed.
390386

391387
Derive NoConfusionHom for EAst.global_decl.
392388

389+
390+
Lemma Forall_Forall2_refl :
391+
forall (A : Type) (R : A -> A -> Prop) (l : list A),
392+
Forall (fun x : A => R x x) l -> Forall2 R l l.
393+
Proof.
394+
induction 1; constructor; auto.
395+
Qed.
396+
397+
Lemma value_head_spec_impl t :
398+
implb (value_head t) (~~ (isLambda t || isFixApp t || isBox t)).
399+
Proof.
400+
destruct t; simpl; intuition auto; eapply implybT.
401+
Qed.
402+
403+
Derive Signature for Forall.
404+
405+
Lemma eval_stuck_fix args argsv mfix idx :
406+
Forall2 eval args argsv ->
407+
isStuckFix (tFix mfix idx) argsv ->
408+
eval (mkApps (tFix mfix idx) args) (mkApps (tFix mfix idx) argsv).
409+
Proof.
410+
revert argsv.
411+
induction args as [|a args IH] using MCList.rev_ind;
412+
intros argsv all stuck.
413+
- apply Forall2_length in all.
414+
destruct argsv; [|easy].
415+
now apply eval_atom.
416+
- destruct argsv as [|? ? _] using MCList.rev_ind;
417+
[apply Forall2_length in all; rewrite app_length in all; now cbn in *|].
418+
apply Forall2_app_r in all as (all & ev_a).
419+
rewrite <- !mkApps_nested.
420+
cbn in *.
421+
destruct (cunfold_fix mfix idx) as [(? & ?)|] eqn:cuf; [|easy].
422+
eapply eval_fix_value.
423+
+ apply IH; [easy|].
424+
destruct (cunfold_fix mfix idx) as [(? & ?)|]; [|easy].
425+
rewrite app_length /= in stuck.
426+
eapply Nat.leb_le in stuck. eapply Nat.leb_le. lia.
427+
+ easy.
428+
+ easy.
429+
+ rewrite app_length /= in stuck.
430+
eapply Nat.leb_le in stuck; lia.
431+
Qed.
432+
433+
Lemma stuck_fix_value_inv argsv mfix idx narg fn :
434+
value (mkApps (tFix mfix idx) argsv) ->
435+
cunfold_fix mfix idx = Some (narg, fn) ->
436+
(Forall value argsv /\ isStuckFix (tFix mfix idx) argsv).
437+
Proof.
438+
remember (mkApps (tFix mfix idx) argsv) as tfix.
439+
intros hv; revert Heqtfix.
440+
induction hv using value_values_ind; intros eq; subst.
441+
unfold atom in H. destruct argsv using rev_case => //.
442+
split; auto. simpl. simpl in H. rewrite H0 //.
443+
rewrite -mkApps_nested /= in H. depelim H.
444+
solve_discr => //.
445+
solve_discr.
446+
Qed.
447+
448+
Lemma stuck_fix_value_args argsv mfix idx narg fn :
449+
value (mkApps (tFix mfix idx) argsv) ->
450+
cunfold_fix mfix idx = Some (narg, fn) ->
451+
#|argsv| <= narg.
452+
Proof.
453+
intros val unf.
454+
eapply stuck_fix_value_inv in val; eauto.
455+
destruct val.
456+
simpl in H0. rewrite unf in H0.
457+
now eapply Nat.leb_le in H0.
458+
Qed.
459+
460+
Lemma value_final e : value e -> eval e e.
461+
Proof.
462+
induction 1 using value_values_ind; simpl; auto using value.
463+
- apply Forall_Forall2_refl in H1 as H2.
464+
move/implyP: (value_head_spec_impl t).
465+
move/(_ H) => Ht.
466+
induction l using rev_ind. simpl.
467+
destruct t; try discriminate.
468+
* repeat constructor.
469+
* repeat constructor.
470+
* rewrite -mkApps_nested.
471+
eapply Forall_app in H0 as [Hl Hx]. depelim Hx.
472+
eapply Forall_app in H1 as [Hl' Hx']. depelim Hx'.
473+
eapply Forall2_app_inv_r in H2 as [Hl'' [Hx'' [? [? ?]]]].
474+
depelim H3. depelim H4.
475+
eapply eval_app_cong; auto.
476+
eapply IHl; auto.
477+
now eapply Forall_Forall2.
478+
destruct l using rev_ind; auto.
479+
eapply value_head_nApp in H.
480+
rewrite isFixApp_mkApps => //.
481+
rewrite -mkApps_nested; simpl.
482+
rewrite orb_false_r.
483+
destruct t; auto.
484+
- destruct f; try discriminate.
485+
apply Forall_Forall2_refl in H0.
486+
now apply eval_stuck_fix.
487+
Qed.
488+
393489
Unset SsrRewrite.
394490
Lemma eval_deterministic {t v v'} :
395491
eval t v ->
@@ -440,27 +536,26 @@ Proof.
440536
+ apply IHev1 in ev'1.
441537
apply mkApps_eq_inj in ev'1; try easy.
442538
depelim ev'1.
443-
noconf H2.
539+
noconf H1; noconf H2.
444540
subst.
445541
apply IHev2 in ev'2; subst.
446-
rewrite H4 in H.
542+
noconf H0.
543+
rewrite H2 in H.
447544
now noconf H.
448545
+ apply IHev1 in ev'1.
449546
apply mkApps_eq_inj in ev'1; try easy.
450547
depelim ev'1.
548+
noconf H1.
451549
noconf H2.
452-
noconf H3.
453550
apply IHev2 in ev'2.
454-
subst.
455-
rewrite H4 in H.
456-
noconf H.
457-
destruct H5 as [|(_ & ?)]; [easy|].
458-
now apply negb_true_iff in H.
551+
subst. noconf H0.
552+
rewrite H2 in H.
553+
noconf H. lia.
459554
+ apply IHev1 in ev'1.
460555
subst.
461-
rewrite isFixApp_mkApps in H2 by easy.
556+
rewrite isFixApp_mkApps in H0 by easy.
462557
cbn in *.
463-
now rewrite orb_true_r in H2.
558+
now rewrite orb_true_r in H0.
464559
+ easy.
465560
- depelim ev'.
466561
+ apply IHev1 in ev'1; solve_discr.
@@ -471,9 +566,7 @@ Proof.
471566
noconf ev'1.
472567
subst.
473568
rewrite H1 in H.
474-
noconf H.
475-
destruct H0 as [|(? & ?)]; [easy|].
476-
now apply negb_true_iff in H0.
569+
noconf H. lia.
477570
+ apply IHev1 in ev'1.
478571
apply IHev2 in ev'2.
479572
now apply mkApps_eq_inj in ev'1 as (ev'1 & <-).

0 commit comments

Comments
 (0)