|
12 | 12 |
|
13 | 13 | (** The Cminor language after instruction selection. *) |
14 | 14 |
|
| 15 | +Require Import Recdef. |
15 | 16 | Require Import Coqlib. |
16 | 17 | Require Import Maps. |
17 | 18 | Require Import AST. |
@@ -504,6 +505,8 @@ with lift_condexpr (p: nat) (a: condexpr) {struct a}: condexpr := |
504 | 505 |
|
505 | 506 | Definition lift (a: expr): expr := lift_expr O a. |
506 | 507 |
|
| 508 | +Definition lift_list (al: exprlist): exprlist := lift_exprlist O al. |
| 509 | + |
507 | 510 | (** We now relate the evaluation of a lifted expression with that |
508 | 511 | of the original expression. *) |
509 | 512 |
|
@@ -582,4 +585,92 @@ Proof. |
582 | 585 | eexact H. apply insert_lenv_0. |
583 | 586 | Qed. |
584 | 587 |
|
585 | | -Global Hint Resolve eval_lift: evalexpr. |
| 588 | +Lemma eval_lift_list: |
| 589 | + forall ge sp e m le w al vl, |
| 590 | + eval_exprlist ge sp e m le al vl -> |
| 591 | + eval_exprlist ge sp e m (w::le) (lift_list al) vl. |
| 592 | +Proof. |
| 593 | + induction 1; simpl; eauto using eval_lift, eval_exprlist. |
| 594 | +Qed. |
| 595 | + |
| 596 | +Global Hint Resolve eval_lift eval_lift_list: evalexpr. |
| 597 | + |
| 598 | +(** Some operations over [exprlist]. *) |
| 599 | + |
| 600 | +Fixpoint length_exprlist (al: exprlist) : nat := |
| 601 | + match al with Enil => O | Econs a al => S (length_exprlist al) end. |
| 602 | + |
| 603 | +Fixpoint app_exprlist (al bl: exprlist) : exprlist := |
| 604 | + match al with Enil => bl | Econs a al => Econs a (app_exprlist al bl) end. |
| 605 | + |
| 606 | +Lemma eval_app_exprlist: forall ge sp e m le al1 al2 vl1 vl2, |
| 607 | + eval_exprlist ge sp e m le al1 vl1 -> |
| 608 | + eval_exprlist ge sp e m le al2 vl2 -> |
| 609 | + eval_exprlist ge sp e m le (app_exprlist al1 al2) (vl1 ++ vl2). |
| 610 | +Proof. |
| 611 | + intros. revert al1 vl1 H. induction 1; simpl; eauto using eval_exprlist. |
| 612 | +Qed. |
| 613 | + |
| 614 | +(** Binding a list of expressions *) |
| 615 | + |
| 616 | +Function bind_exprs_rec (al: exprlist) (args: exprlist) (f: exprlist -> expr) |
| 617 | + {measure length_exprlist al} : expr := |
| 618 | + match al with |
| 619 | + | Enil => f args |
| 620 | + | Econs a al => |
| 621 | + Elet a (bind_exprs_rec (lift_list al) |
| 622 | + (app_exprlist (lift_list args) (Econs (Eletvar O) Enil)) |
| 623 | + f) |
| 624 | + end. |
| 625 | +Proof. |
| 626 | + intros. replace (length_exprlist (lift_list al0)) with (length_exprlist al0). |
| 627 | +- simpl; lia. |
| 628 | +- generalize al0. induction al1; simpl; f_equal; auto. |
| 629 | +Qed. |
| 630 | + |
| 631 | +Definition bind_exprs (al: exprlist) (f: exprlist -> expr) : expr := |
| 632 | + bind_exprs_rec al Enil f. |
| 633 | + |
| 634 | +Lemma eval_bind_exprs_gen: forall (P: val -> Prop) ge sp e m le al vl f, |
| 635 | + eval_exprlist ge sp e m le al vl -> |
| 636 | + (forall args, |
| 637 | + eval_exprlist ge sp e m (rev vl ++ le) args vl -> |
| 638 | + exists v, eval_expr ge sp e m (rev vl ++ le) (f args) v /\ P v) -> |
| 639 | + exists v, eval_expr ge sp e m le (bind_exprs al f) v /\ P v. |
| 640 | +Proof. |
| 641 | + intros until m. |
| 642 | + assert (REC: forall al args f le vl1 vl2, |
| 643 | + (forall args', |
| 644 | + eval_exprlist ge sp e m (rev vl2 ++ le) args' (vl1 ++ vl2) -> |
| 645 | + exists v, eval_expr ge sp e m (rev vl2 ++ le) (f args') v /\ P v) -> |
| 646 | + eval_exprlist ge sp e m le args vl1 -> |
| 647 | + eval_exprlist ge sp e m le al vl2 -> |
| 648 | + exists v, eval_expr ge sp e m le (bind_exprs_rec al args f) v /\ P v). |
| 649 | + { intros until f. functional induction (bind_exprs_rec al args f); intros until vl2; intros F A B. |
| 650 | + - inv B. apply F. rewrite app_nil_r. auto. |
| 651 | + - inv B. |
| 652 | + destruct (IHe0 (v1 :: le) (vl1 ++ v1 :: nil) vl) as (v & X & Y). |
| 653 | + + intros. |
| 654 | + assert (EQ: rev vl ++ v1 :: le = rev (v1 :: vl) ++ le). |
| 655 | + { simpl. rewrite app_ass. auto. } |
| 656 | + rewrite EQ. apply F. rewrite <- EQ. rewrite app_ass in H. auto. |
| 657 | + + apply eval_app_exprlist. |
| 658 | + * apply eval_lift_list; auto. |
| 659 | + * repeat constructor. |
| 660 | + + apply eval_lift_list; auto. |
| 661 | + + exists v; split; eauto using eval_expr. |
| 662 | + } |
| 663 | + intros. eapply REC with (args := Enil); eauto using eval_exprlist. |
| 664 | + assumption. |
| 665 | +Qed. |
| 666 | + |
| 667 | +Lemma eval_bind_exprs: forall ge sp e m le al vl f v, |
| 668 | + eval_exprlist ge sp e m le al vl -> |
| 669 | + (forall args, |
| 670 | + eval_exprlist ge sp e m (rev vl ++ le) args vl -> |
| 671 | + eval_expr ge sp e m (rev vl ++ le) (f args) v) -> |
| 672 | + eval_expr ge sp e m le (bind_exprs al f) v. |
| 673 | +Proof. |
| 674 | + intros. exploit (eval_bind_exprs_gen (fun v' => v' = v)); eauto. |
| 675 | + intros (v' & A & B). subst v'; auto. |
| 676 | +Qed. |
0 commit comments